Sunteți pe pagina 1din 6

Articol Dan Pracsiu

articol pe campion.edu.ro
http://campion.edu.ro/arhiva/www/arhiva_2009/pape
rs/paper21.pdf
Vectori de biti
http://ler.is.edu.ro/~cex_is/Informatica/2014/teme/b
iti.pdf

Operaii pe bii
Lista operatorilor pe bii:

~ - negaie pe bii
& - i pe bii (and)
| - sau pe bii (or)
^ - sau exclusiv pe bii (xor)
<< - deplasare la stnga pe bii (shift left)
>> - deplasare la dreapta pe bii (shift right)
S menionm c operatorii logici pe bii se aplic numai operanzilor de tip ntreg. n exemplele
urmtoare, vom considera c numerele sunt reprezentate pe 16 bii fr semn (adic de tip
unsigned short).

Negaia pe bii este operator unar i are ca efect schimbarea biilor 0 n 1 i biilor 1 n 0. n
consecin, dac a = 0000000000001110(2), atunci ~a = 1111111111110001(2)

Operatorii &, |, ^ sunt operatori binari. Tabelele operaiilor sunt urmtoarele:

Articol Dan Pracsiu

Considernd op ca fiind oricare din operatorii &, |, ^, o expresie de forma x op y opereaz asupra
biilor operanzilor x i y. Astfel, dac x = 1110(2) i y = 1101(2) , atunci x & y = 1100(2), x | y =
1111(2), iar x ^ y = 0011(2).

Operatorii de deplasare, << i >>, sunt operatori binari. Expresia x << i este echivalent cu
expresia x * 2i. De fapt acest operator elimin cei mai din stnga i bii ai lui x i adaug la dreapta i
bii de 0. De exemplu, dac x = 0000000000001110(2), atunci x << 2 nseamn
0000000000111000(2) = 56 (adic 14 * 4).
Expresia x >> i este echivalent cu x div 2i (mprirea ntreag a lui x prin 2i). Operatorul de
deplasare la dreapta elimin cei mai din dreapta i bii ai lui x i adaug la stnga i bii de 0. De
exemplu, dac x = 0000000000001110(2), atunci x >> 2 nseamn 0000000000000011(2) = 3
(adic 14 div 4).

Probleme rezolvate

1. Se consider un numr natural n. S se verifice dac n este par sau impar.

Rezolvare: Utilizm operatorul &. Acesta are rol de testare a biilor. 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 numr n,
expresia n & 1 furnizeaz ca rezultat cel mai din dreapta bit. Putem scrie atunci urmtoarea
secven:

cin >> n ;
if (( n & 1 ) == 1) cout << "Numar impar" ;
else cout << "Numar par" ;
De menionat faptul c operatorii pe bii au o prioritate mic, de aceea am preferat o pereche
suplimentar de paranteze n expresia instruciunii if. Expresia n & 1 == 1 este interpretat de
compilator ca fiind n & (1 == 1)

2. Se citete un numr natural k <= 15. S se afieze valoarea 2k.

Rezolvare: Ne bazm pe operatorul de deplasare la stnga pe bii. Expresia care furnizeaz


rspunsul corect este 1 << k. Deci secvena va fi:

Articol Dan Pracsiu

cin >> k ;
cout << (1 << k) ;
3. Se consider un numr natural n. S se determine ctul i restul mpririi lui n la 8.
Generalizare: s se determine ctul i restul mpririi lui n la un numr care este putere a lui 2.

Rezolvare: Pentru determinarea ctului se utilizeaz deplasarea la dreapta cu 3 bii (ceea ce este
echivalent cu mprirea prin 23). Pentru rest se utilizeaz expresia n & 7 (unde 7 vine de la 23- 1 ).
Deoarece 7 = 1112 atunci toi biii lui n vor fi anulai, cu excepia ultimilor 3 cei mai din dreapta.
Generalizearea se obine imediat, nlocuind 23 cu 2k.

cin >> n ;
cout << "Catul este : " << (n >> 3) ;
cout << "Restul este : " << (n & 7) ;
4. Se consider un numr 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 numrm
ci bii de 1 are n n baza 2. Dar o soluie 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 biii de la dreapta sunt acum toi 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 numr natural n. S se afieze reprezentarea lui n n baza 2.

Rezolvare: Ne bazm pe faptul c n memorie n este deja reprezentat n baza 2, deci trebuie s-i
afim biii de la stnga la dreapta. Presupunnd c n este reprezentat pe 16 bii, pe acetia i
numerotm de la dreapta la stnga cu numere de la 0 la 15. Pentru a obine bitul de pe poziia i (0
<= i <= 15), utilizm expresia (n >> i) & 1. Nu rmne dect s utilizm expresia pentru
fiecare i ntre 0 i 15.

Articol Dan Pracsiu

cin >> n ;
for (int i=15 ; i >= 0 ; i--)
cout << ((n >> i) & 1) ;
6. Se consider dou numere naturale n i i (0 <= i <= 15). S se marcheze cu 1 bitul i al lui n.

Rezolvare: Vom seta valoarea 1 la bitul i, indiferent de valoarea memorat anterior (0 sau 1).
Pentru setare, utilizm operatorul sau pe bii. Expresia care realizeaz aceasta este n | (1 <<

i) . S ne amintim dintr-un exerciiu anterior c 1 << i nseamn 2i. Expresia n | 2i nu va


modifica dect bitul i care ne intereseaz, restul rmnnd nemodificai, datorit faptului c dac b
este un bit atunci b | 0 este egal cu b.

7. Se consider dou numere naturale a i b, ambele cuprinse ntre 0 i 255. Se cere s se


memoreze cele dou numere ntr-un ntreg n reprezentabil pe 16 bii fr semn (deci de tip
unsigned short).

Rezolvare: Cele dou numere a i b pot fi reprezentate pe 8 bii. De aceea cei 16 bii ai lui n sunt
suficieni. Stocm a pe primii 8 bii ai lui n, iar pe b pe ultimii 8 bii ai lui n. n = a * 256 + b ;
De asemenea, dac se cunoate n, se pot obine valorile lui a i b astfel: a = n >> 8 ; // sau

a = n / 256
b = n & 255 ; // sau b = n % 256 ;
8. Codificare/decodificare. Considerm un numr pe care dorim s-l codificm, apoi s-l
decodificm.

Rezolvare: O modalitate simpl de codificare i decodificare este utilizarea operatorului pe bii


XOR. Pentru aceasta considerm o masc (o parol) i ne bazm pe o proprietate interesant a
operatorului XOR: a ^ b ^ b = a. Deci a ^ b realizeaz codificarea lui a, iar (a ^ b) ^ b realizeaz
decodificarea. Proprietatea se bazeaz pe faptul c b ^ b = 0, pentru orice b, iar a ^ 0 = a. Metoda
poate fi aplicat i pentru codificarea unui text utiliznd o parol dat. Cu ajutorul parolei aplicat
peste textul iniial se obine codificarea, iar o a doua aplicare a parolei peste codificare se obine
textul iniial. Secvena care realizeaz codificarea/decodificarea unui numr este:

int n, masca;
n = 65 ;
masca = 100 ;

Articol Dan Pracsiu

cout << "\nValoarea initiala a lui n : " << n ;


n = n ^ masca ;
cout<< "\nValoarea codificata a lui n : " << n ;
n = n ^ masca ;
cout<< "\nValoarea decodificata a lui n : " << n ;

Problema rezolvata
Sa se scrie o functie getbits(x,p,n) care returneaza, aliniat la dreapta, un camp de n biti dintr-un
intreg fara semn x, incepand cu pozitia p a lui x. Se considera ca bitul cel mai putin semnificativ al lui
x are pozitia 0.

#include <iostream.h>
unsigned getbits(unsigned x, int p, int n)
{
return (x >> (p+1-n)) & ~(~0 << n);
}
int main()
{
unsigned x;
int p=6,n=3;
cout<<"Numar initial: ";
cin>>x;
cout<<"Valoarea extrasa:"<<getbits(x,p,n));
}
Se observa ca in functia getbits:
secventa x >> (p+1-n) aliniaza la dreapta bitii de extras
secventa creeaza masca de extragere, adica 000...0111

Probleme propuse
1. Sa se scrie o functie setbits(x,p,n,y), care returneaza un intreg x avand n biti incepand de la pozitia
p egali cu cei mai din dreapta n biti ai intregului y. Restul bitilor lui x raman nemodificati.

Articol Dan Pracsiu


2. Sa se scrie o functie bin(x) care afiseaza reprezentarea binara a unui intreg x, utilizand operatorii
de deplasare la nivel de bit.