View Full Version : [C++] Operatori bitwise - come definire il risultato di una operazione !?!
Sera,
oggi mi è capitato per puro caso di ricorrere all'uso degli operatori bitwise e ho avuto una difficoltà. Più che una difficoltà una carenza.
Mi spiego meglio:
Quando guardai gli operatori bitwise, a loro tempo, ne studiai solo il significato e ho sempre e solo visto esempi diretti sui bit.
Oggi li ho usati su variabili intere, passando gli argomenti a una funzione SDL.
Precisamente SDL_Init(Uint32 flags) (http://sdl.beuc.net/sdl.wiki/SDL_Init).
Mi è quindi venuta una illuminazione: provare a realizzare a mia volta una funzione che possa agire come SDL_Init, cioè dirigere il flusso di esecuzione in base al valore ottenuto con l'or bitwise sulle varie macro passate.
esempio della funzione SDL con l'OR bitwise:
SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO);
Quindi con la premessa che praticamente passo un nuovo valore, quindi ne SDL_INIT_AUDIO ne SDL_INIT_VIDEO, ma un valore calcolato in base al risultato della operazione sui due numeri convertiti in binario, fare il semplice controllo del valore. (se c'è una soluzione migliore che mi sfugge ditela pure :P).
Per sapere quindi il risultato l'unico metodo che conosco (e che ho sempre visto) è quello di convertire direttamente i numeri decimali in binari, eseguire il calcolo e riconvertire in decimale.
Quindi vi chiedo: esiste qualche operazione aritmetica per verificare direttamente il risultato decimale di una operazione di bitwise senza dover convertire il numero in binario, eseguire l'operazione e quindi riconvertire in decimale ?
Sò che sugli operatori di shift si ottiene così:
- per x >> y: x/2^n
- per x << y: x*2^n
Io mi riferisco ad operazioni utili a me per sapere sempre quale risultato aspettarmi (anche se qualuno potrebbe rispondermi:"semplice,assegna alla variabile la stessa operazione bitwise, in modo da avere automaticamente il suo valore", ed io replicherei "ma voglio saperlo per cultura personale, non perchè ogni volta mi metto a fare i calcoli a mente, anche se non guasterebbe").
Se sapete rispondere anche per lo XOR il NOT, e lo AND, fatevi avanti :D
Buona serata a tutti.
[EDIT]
Da questo link (http://www.livephysics.com/ptools/bitwise-operation.php), deduco che l'unico metodo pratico sia farlo manualmente :s. Ovviamente più che manualmente conviene un software, ma non è questo il punto.
Attendo qualcuno che screditi questa tesi.
SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO);
Non ho capito cosa intendi di preciso con "verificare manualmente". Di solito e' sufficiente fare un AND del valore passato con il "bit" che vuoi verificare
Ad esempio l'implementationze di SDL_Init potrebbe avere al suo interno qualcosa del genere
void SDL_Init( int flags )
{
if ( flags & SDL_INIT_AUDIO ) // initialize the audio subsystem ...
...
}
Questo funziona senza sorprese, ovviamente, fintanto che tu dedichi ogni specifico bit ad una funzionalita' precisa ( che e' quel che si usa di solito ).
Quindi vi chiedo: esiste qualche operazione aritmetica per verificare direttamente il risultato decimale di una operazione di bitwise senza dover convertire il numero in binario, eseguire l'operazione e quindi riconvertire in decimale ?
L'operazione binaria NOT:
a = ~b
su una stringa di n bit corrisponde all'operazione decimale intera:
a = (2^n)-1-b
per AND, OR e XOR non mi viene al momento in mente nulla di simile.
ciao!
british
Passando due interi con un operatore di bitwise non ottengo solo un nuovo valore?
Nel senso che: 25|20 = 29, flags non contiene il solo intero 29?
Quindi se faccio come dici un if( flags & SDL_INIT_AUDIO )
se è come dico io ritorna sempre un valore diverso da zero e quindi anche se io ho solo fatto passato "SDL_INIT_AUDIO | SDL_INIT_VIDEO", e faccio il check con l'if sulla macro SDL_INIT_CDROM dovrebbe eseguire anche quel blocco, seppure NON ci sia quel valore.
Per manualmente intendo proprio un calcolo senza l'utilizzo di software, farlo a mente potrebbe essere arduo dato che bisogna convertire il numero in binario, tenere a mente il binario mentre esegui il calcolo con un altro binario e poi dal risultato ritornare a un intero decimale. Quindi manualmente, con carta e penna.
Mi interessa per sapere a priori quale risultato otterrò con una operazione di bitwise senza dover "testare" il software... metti che un giorno mi capiterà a lavoro (quando lavorerò) non credo sia bello farsi vedere mentre "provo" qual'è il risultato.
Ritornando al metodo da te consigliato: perchè quindi dovrebbe funzionare? Flags ora non contiene più i valori nè di INIT_VIDEO ne INIT_AUDIO ma un nuovo valore, quindi anche facendo un AND bitwise con il valore di una altra non mi restituisce zero, no? (Se non ho zero l'if viene eseguito comunque, quindi anche un controllo con una altra macro verrebbe superato e verrebbe inizializzato il device anche senza averlo chiesto).
Per questo motivo, l'unica soluzione che mi è venuta in mente è proprio quella di controllare il valore del risultato bitwise calcolato in precedenza con la variabile flags (se flags equivale 29 e sò che INIT_VIDEO è 25 e INIT_AUDIO è 20, sò che ho passato questi due interi decimali. Ovviamente nel software potrei confrontare con
if((SDL_INIT_VIDEO | SDL_INIT_AUDIO) == flags) //.. fai questo
Anche se questi metodi mi sembrano molto macchinosi, dato che se le macro son tante il numero di combinazioni aumenta e di conseguenza la complessità dell'istruzione.
Insomma, oltre che trovare il metodo per farlo nel software, mi interessa, se esiste, l'operazione aritmetica per sapere quale valore decimale otterrei, quindi, in parole povere, il semplice SDL_INIT_VIDEO | SDL_INIT_AUDIO quale operazioni aritmetiche compie?
Spesso ci sono vari algoritmi per verificare una condizione, ma in questo caso l'unica via mi sembra proprio quella di trasformare il valore in binario e fare i calcoli...
Spero di essere stato chiaro.
A dir la verità rileggendo il post mi sembra di aver messo altra carne al fuoco...
Mi interessa l'implementazione software e se esiste un possibile calcolo aritmetico per calcolare il risultato di una operazione bitwise (una alternativa a questo (http://www.livephysics.com/ptools/bitwise-operation.php) metodo di risoluzione.
[EDIT]
Rettifico, ho testato la tua soluzione:
#include <iostream>
#include <cstdlib>
using namespace std;
#define PRIMO 25
#define SECONDO 20
void test( int bitwise );
int main( )
{
test( PRIMO|SECONDO );
getchar();
return( EXIT_SUCCESS );
}
void test( int bitwise )
{
if( bitwise & PRIMO )
{
cout << "hai passato primo" << endl;
}
if( bitwise & SECONDO )
{
cout << "hai passato secondo" << endl;
}
return;
}
... e funziona :s.
Mah... non ci ho capito molto allora.
Se io passo PRIMO|SECONDO, non ottengo solo il risulato di questa operazione!?!
Quindi se poi uso & con questo risultato (PRIMO|SECONDO) e PRIMO, dovrei ottenere un nuovo valore, no? Comunque diverso da zero....
ommamma... mi stà sicuramente sfuggendo qualcosa...
L'operazione binaria NOT:
a = ~b
su una stringa di n bit corrisponde all'operazione decimale intera:
a = (2^n)-1-b
per AND, OR e XOR non mi viene al momento in mente nulla di simile.
ciao!
british
Ecco intendevo proprio questo :)
Grazie british!
Perdonami ma ho davvero difficoltà a comprendere il senso complessivo del tuo quesito, per cui ti rispondo solo a brandelli.
Iniziamo col dire che ciò che ti ha suggerito marco.r è senza dubbio corretto.
Nel senso che: 25|20 = 29, flags non contiene il solo intero 29?
Occhio, stai facendo un OR: 29 "contiene" i contributi pesati comuni a 25 e a 20 presi una sola volta ( 25 = 16+8+1; 20 = 16+4; 29 = 16 +4+1 ).
Quindi se faccio come dici un if( flags & SDL_INIT_AUDIO )
se è come dico io ritorna sempre un valore diverso da zero
Qui stai facendo un AND, che ritorna ( meglio: restituisce ) un valore diverso da zero se e solo se i due valori hanno almeno un bit asserito ( = 1 ) nella stessa posizione.
Il metodo indicato da marco.r funziona correttamente e senza ambiguità grazie a una premessa da lui fatta:
Questo funziona senza sorprese, ovviamente, fintanto che tu dedichi ogni specifico bit ad una funzionalita' precisa ( che e' quel che si usa di solito ).
In altre parole, le varie macro SDL_INIT_ECC viste in binario hanno un solo bit asserito, ovverosia, in decimale, assumono valori del tipo 2^n con n >= 0
ciao!
british
Perdonami ma ho davvero difficoltà a comprendere il senso complessivo del tuo quesito, per cui ti rispondo solo a brandelli.
Perdonami tu, evidentemente oggi non riesco a spiegarmi come vorrei. Quando non riesco ad entrare nell'ottica giusta mi capita di scrivere parecchio quando basterebbero poche e precise parole per spiegare subito il problema.
Iniziamo col dire che ciò che ti ha suggerito marco.r è senza dubbio corretto.
Già, i fatti gli danno ragione :p
Occhio, stai facendo un OR: 29 "contiene" i contributi pesati comuni a 25 e a 20 presi una sola volta ( 25 = 16+8+1; 20 = 16+4; 29 = 16 +4+1 ).
In questo caso sarebbe meglio che gli dia una bella ripassatina, perchè mi sà che è questo che mi sfugge.
Qui stai facendo un AND, che ritorna ( meglio: restituisce )
:sbavvv: che errore madornale!
... speriamo solo non passi di qui PGI-Bis :asd:
un valore diverso da zero se e solo se i due valori hanno almeno un bit asserito ( = 1 ) nella stessa posizione.
Il concetto mi è chiaro, in questo caso sarà meglio che ci rimetta un po' di impegno e torni a guardarli... quando una cosa non mi serve, tendo a guardarla con superficialità... è un errore lo sò ma la quantità immane di cose da studiare mi induce a studiare "a pezzi" quello che mi serve in quel momento, per questo punto molto a fare tanti esercizi, per trovarmi nella condizione di dover usare cose nuove.
In altre parole, le varie macro SDL_INIT_ECC viste in binario hanno un solo bit asserito, ovverosia, in decimale, assumono valori del tipo 2^n con n >= 0
ciao!
british
Quindi per scegliere il valore delle varie macro bisogna prestare attenzione o posso andare "superficialmente" assegnando come valore i più classici 0, 1, 2, 3 etc... ?
Perchè in tal caso dovrei trovare il modo di sapere se un tale numero ha un bit asserito corrispondente a quello di un'altro valore delle macro.
Comunque per non scomodarvi troppo, mi farò una ripassatina dell'argomento, così da non costringervi a dire cose trite e ritrite, e nel caso non riesca a capire qualcosa, mi prendo la libertà di richiedere a voi :)
Per ora, grazie mille dell'aiuto e dell'attenzione!
Rettifico, ho testato la tua soluzione:
... e funziona :s.
Mah... non ci ho capito molto allora.
Se io passo PRIMO|SECONDO, non ottengo solo il risulato di questa operazione!?!
Quindi se poi uso & con questo risultato (PRIMO|SECONDO) e PRIMO, dovrei ottenere un nuovo valore, no? Comunque diverso da zero....
ommamma... mi stà sicuramente sfuggendo qualcosa...
Quando fai operazioni bitwise, non pensare ai numeri, ma ai singoli bit.
Esempio. Andando a guardare l'header di sdl, vedrai che i numeri di cui parli sopra sono definiti come segue:
#define SDL_INIT_TIMER 0x00000001
#define SDL_INIT_AUDIO 0x00000010
#define SDL_INIT_VIDEO 0x00000020
#define SDL_INIT_CDROM 0x00000100
#define SDL_INIT_JOYSTICK 0x00000200
#define SDL_INIT_NOPARACHUTE 0x00100000 /* Don't catch fatal signals */
#define SDL_INIT_EVENTTHREAD 0x01000000 /* Not supported on all OS's */
#define SDL_INIT_EVERYTHING 0x0000FFFF
Se tu guardi la rappresentazione binaria dei numeri, ottieni i seguenti valori
0000000000000000000000001
0000000000000000000010000
0000000000000000000100000
0000000000000000100000000
0000000000000001000000000
0000100000000000000000000
1000000000000000000000000
0000000001111111111111111
in pratica l'ultimo bit da destra indica se vuoi inizializzare il timer, quello piu' a sinistra se invece vuoi il thread degli eventi e cosi' via.
Quando tu fai SDL_INIT_TIMER | SDL_INIT_AUDIO ottieni come valore
0000000000000000000000001 OR
0000000000000000000010000 =
=========================
0000000000000000000010001
Se voglio vedere se l'utente ha selezionato SDL_INIT_AUDIO mi basta vedere se il quinto bit e' acceso, ovvero fare l'AND bitwise con SDL_INIT_AUDIO stesso:
0000000000000000000010001 AND
0000000000000000000010000 =
=========================
0000000000000000000010000
Ah! Ecco allora quale era il mio errore.
Beh non sò proprio come ringraziarti :)
Sei stato gentilissimo, io pensavo sempre al decimale e non più ai binari, per questo non riuscivo a capire :rolleyes:
Adesso farò qualche test coi vari operatori.
Meno male che me lo hai esposto perchè leggendo le varie guide pensavo fossero altre le cose che mi sfuggivano.
Grazie ancora e buona giornata!
PS. se qualcuno conosce le varie operazioni aritmetiche corrispondente all'utilizzo di un operatore bitwise, è il benvenuto.
Per ora grazie a british conosco quella del NOT e quelle due degli shift a destra e a sinistra che conoscevo già...
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.