Sunteți pe pagina 1din 3

OPERATII PE BITI

Proiect realizat de Timus George, clasa XR

De cele mai multe ori, fie într-un joc, fie în viața de zi cu zi a unui programator,
atunci când implementăm o metodă pe care o folosește o aplicație și dorim ca
acea metodă să funcționeze ca una eficientă, trebuie să analizăm complexitatea
algoritmului implementat. observăm că în practică algoritmul este mai lent decât
ne-am dori, încercăm să găsim un algoritm cu o complexitate mai mică.
Nu trebuie să uităm că atunci când vorbim de complexitate algoritmică, este o
aproximare a vitezei algoritmice, nu o măsură absolută. Pentru volume mici de
date, uneori nu există nicio diferență între O(n) și O(n log n) sau O(n3 / 2).
Operațiile pe biți sunt utilizate pe scară largă în optimizatoare, în special atunci
când se ocupă direct cu numere de bază 2 sau cu puteri de 2.
Operatorii C++ pe biți sunt implementați în limbaj de asamblare, ceea ce îi face
foarte rapidi. Operatorii pe biți, după cum sugerează și numele, lucrează pe biții
(semnați și nesemnați) ai numerelor întregi. Acest lucru poate părea ciudat, mai
ales având în vedere că cea mai mică zonă de memorie cu o adresă este un octet,
care constă de fapt din 8 biți. În primul rând, pentru a înțelege cum funcționează
acești operatori, trebuie să înțelegem cum sunt reprezentați în C++ ca întreg.
EXEMPLE:
1. Se consideră un număr natural n. Să se verifice dacă n este par sau impar.
Rezolvare: Utilizăm operatorul &. Acesta are rol de testare a biţilor. Dacă n este impar, atunci
reprezentarea sa în baza 2 va avea cel mai din dreapta bit pe 1. De exemplu, n = 13 se scrie în
baza 2 ca 1101. Atunci 1101 & 1 = 1. Dacă n este par, atunci cel mai din dreapta bit va fi 0. De
exemplu, n = 14 se scrie în baza 2 ca 1110. Atunci 1110 & 1 = 0. Iată că pentru orice număr n,
expresia n & 1 furnizează ca rezultat cel mai din dreapta bit. Putem scrie atunci următoarea
secvenţă:
cin >> n ;
if (( n & 1 ) == 1) cout << "Numar impar" ;
else cout << "Numar par" ;
De menţionat faptul că operatorii pe biţi au o prioritate mică, de aceea am preferat o pereche
suplimentară de paranteze în expresia instrucţiunii if. Expresia n & 1 == 1 este interpretată de
compilator ca fiind n & (1 == 1)

2. Se citeşte un număr natural k <= 15. Să se afişeze valoarea 2k.


Rezolvare: Ne bazăm pe operatorul de deplasare la stânga pe biţi. Expresia care furnizează
răspunsul corect este 1 << k. Deci secvenţa va fi:
cin >> k ;
cout << (1 << k) ;
3. Se consideră un număr natural n. Să se determine câtul şi restul împărţirii lui n la 8.
Generalizare: să se determine câtul şi restul împărţirii lui n la un număr care este putere a lui
2.
Rezolvare: Pentru determinarea câtului se utilizează deplasarea la dreapta cu 3 biţi (ceea ce
este echivalent cu împărţirea prin 23). Pentru rest se utilizează expresia n & 7 (unde 7 vine de la
23- 1 ). Deoarece 7 = 1112 atunci toţi biţii lui n vor fi anulaţi, cu excepţia ultimilor 3 cei mai din
dreapta. Generalizearea se obţine imediat, înlocuind 23 cu 2k.
cin >> n ;
cout << "Catul este : " << (n >> 3) ;
cout << "Restul este : " << (n & 7) ;

4. Se consideră un număr natural n. Să se verifice dacă n este sau nu o putere a lui 2.


Rezolvare: Acesta este o problemă destul de cunoscută. Dacă n este o putere a lui 2, atunci
reprezentarea sa în baza 2 are un singur bit 1, restul fiind 0. O primă idee ar fi deci să numărăm
câţi biţi de 1 are n în baza 2. Dar o soluţie mai rapidă se bazează pe ideea că dacă n este o
putere a lui 2, deci de forma 0000000000100000, atunci n-1 are reprezentarea de forma
0000000000011111, adică bitul 1 s-a transformat în 0, iar biţii de la dreapta sunt acum toţi 1.
Deci o expresie de forma n & (n-1) va furniza rezultatul 0 dacă şi numai dacă n este o putere a
lui 2.
cin >> n ;
if ( (n & (n-1)) == 0 ) cout << "n este putere a lui 2" ;
else cout << "n nu este putere a lui 2" ;
5. Se consideră un număr natural n. Să se afişeze reprezentarea lui n în baza 2.
Rezolvare: Ne bazăm pe faptul că în memorie n este deja reprezentat în baza 2, deci trebuie să-i
afişăm biţii de la stânga la dreapta. Presupunând că n este reprezentat pe 16 biţi, pe aceştia îi
numerotăm de la dreapta la stânga cu numere de la 0 la 15. Pentru a obţine bitul de pe poziţia i
(0 <= i <= 15), utilizăm expresia (n >> i) & 1. Nu rămâne decât să utilizăm expresia pentru fiecare
i între 0 şi 15.
cin >> n ;
for (int i=15 ; i >= 0 ; i--)
cout << ((n >> i) & 1) ;

S-ar putea să vă placă și