Sunteți pe pagina 1din 6

OPERATII CU BITI IN LIMBAJ C++

De cele mai multe ori, atât în concursuri cât şi în viaţa de zi cu zi a programatorului,atunci


când implementăm o metodă care este folosită de o aplicaţie şi vrem să facem
aceastămetodă eficientă ca timp de execuţie, trebuie să analizam complexitatea
algoritmuluiimplementat şi dacă observăm că în praccă algoritmul este mai încet decât ne
dorim noi să încercăm să găsim un algoritm cu un ordin de complexitate mai mic.Nu trebuie
să uităm că ceea ce numim complexitatea unui algoritm este o aproximare a vitezeiunui
algoritm şi nu o măsură absolută. Pentru dimensiuni mici ale datelor, câteodată nu
seobservă diferenţă dintre O(n) şi O(n log n) sau O(n3/2).Operațiile pe biți sunt folosite
foarte pentru opmizarea programelor, în special atunci cândeste nevoie în mod direct de
lucrul cu numere în baza 2, sau cu puteri ale lui 2. Operatorii pebiți din C++ sunt
implementați în limbaje de asamblare, ceea ce îi face foarte rapizi.Operatorii pe biți, după
cum le zice și numele, lucrează la nivelul biților numerelor întregi(signed și unsigned). Poate
părea ciudat, mai ales având în vedere că cea mai mică zonă dememorie ce are o adresă
este byte-ul, care este compus de fapt din 8 biți. În primul rând,pentru a înțelege cum
funcționează acești operatori, trebuie înțeles modul în care suntreprezentați întregii în C++.
În connuare vom încerca să găsim soluţii mai rapide decât cele naive pentru unele operaţii
debază (toate operaţiile vor fi implementate pentru întregi pozitivi reprezentaţi pe 32 de
biţi).
Reprezentarea binară a întregilor în C++

Vom începe cu întregii cu semn. Pentru simplitate, mă voi referi direct la tipul int. O
variabilă dep int e reprezentată pe 4 bytes(octeti), adică pe 32 de biți. Dintre aceștia,
primul bit (cel maidin stânga) se numește bit de semn, deoarece acesta indică semnul
numărului. Dacă numărul e pozitiv, valoarea bitului de semn este 0, iar dacă e negativ 1. În
cazul numerelor pozitive, peceilalți 31 de biți, de la stânga la dreapta, se află
reprezentarea în baza 2 a numărului.

0 1 0 1 1 0 0 0

88=26+24 +23

In cazul numerelor negative, pe cei 32 de biți (cu tot cu cel de semn), este reprezentat
numărul într-un cod complementar față de modulul său, numit Two's complement. Mai
există douămoduri importante de reprezentare a întregilor negativi, Signed magnitude și
One'scomplement. Ele sunt mai ușor de înțeles pentru oameni, însă calculatoarele lucrează
mai încetcu ele. În plus, un dezavantaj major al lor este faptul că −0 și +0 sunt reprezentați
diferit.
OPERATII PE BITI

În codicarea folosită de C++, pentru numărul negav −x se va reține reprezentarea lui


232−x.Această reprezentare garantează că bitul de semn va  1 doar pentru numerele
strict negave.Iată cum arată două numere reținute pe un p întreg de 8 biți:

1 1 0 1 1 0 0 0

-40=-(2^8-(2^7+2^6+2^4+2^3))=-(256-216)
Pentru celelalte tipuri întregi cu semn treaba stă fix la fel, doar că 32-ul luat ca exemplu va fi
înlocuit cu numărul de biți folosit de tipul respectiv. De exemplu, dacă ne referim la un tip
cusemn pe trei biți (care de fapt nu există, întrucât 3 nu este o putere a lui 2), numerele ce
pot fi reprezentate pe el sunt:
000=1
001=1
010=2
011=3
100=-4
101=-3
110=-2
111=-1
După cum se poate vedea, se numără de la 0 la numărul pozitiv maxim (3), iar după ce bitul
desemn devine 1, se numără de la cel mai mic număr negav (−4) la cel mai mare (−1).La
întregii fără semn e aproape la fel, doar că nu există bit de semn, deoarece se șe că
toatevalorile ce se pot reține într-un p întreg fără semn sunt pozitive. Așadar, pe cei 32 de
biți aiunui unsigned int, se reține reprezentarea în baza 2 a numărului stocat în variabila
respectivă.

Operatorii pe biți în C++

Acum putem analiza cum funcționează fiecare operator pe biți din C++. În funcție de
numărulde operanzi, operatorii pot fi unari sau binari. În plus, există și operatori compuși
de atribuire pebiți.
OPERATII PE BITI

Operatorul de negație pe biți (~) este singurul operator unar pe biți. Acesta schimbă
fiecare bital operandului în opusul său. Deci, biții 0 vor deveni 1, iar biții 1 vor deveni 0.

x = 00010110

~x = 11101001

Operatorii logici pe biți (|, &, ^)

Acești operatori efectuează operații logice asupra biților de pe aceeași poziție din cele
douănumere. Pentru simplitate, voi nota cei doi operanzi cu a și b, rezultatul cu c, iar cu xi
bitul de pepoziția i din x.

După aplicarea disjuncției pe biți (|), ci va  1 dacă măcar unul dintre ai și bi este 1, iar 0 în
cazcontrar.

01110010 |

11000110

--------

11110110

Dacă operația efectuată este conjuncția pe biți (&), ci va fi 1 dacă ai și bi sunt ambele 1, iar
0 dacă nu.

01010100 &

11001110

--------

10101101

OPERATII PE BITI

a b a|b a&b a^b

0 0 0 0 0

0 1 1 0 1

1 0 1 0 1

1 1 1 1 0
Operatorii de deplasare a biților (<<, >>)

Vom nota operandul din stânga cu a, iar pe cel din dreapta cu b. Operatorul de deplasare
lastânga (shift left , <<) mută toți biții lui a la stânga cu b poziții. Biții noi, ce vor apărea la
dreapta,vor  0. Cu alte cuvinte, se șterg primii b biți din a, iar în dreapta sunt inserați b
biți cu valoarea0. Operatorul de deplasare la dreapta (shift right, >>) funcționează
asemănător, doar că direcțiade deplasare este, desigur, la dreapta. În ambele cazuri, b
poate fi chiar și negativ.

a =00110010

a << 3=10010000

a =00110010

a>>1=00011001

După cum am zis, există și operatori compuși de atribuire pe biți (|=, &=, ^=, <<=, >>=).
Aceștia alucrează direct asupra primului operand, rezultatul operației fiind stocat în
acesta.

(a |= b)⇔(a = a | b)

(a &= b)⇔(a = a & b)

(a ^= b)⇔(a = a ^ b)

(a <<= b)⇔(a = a << b)

(a >>= b)⇔(a = a >> b)

Operatorii de deplasare, << şi >>, sunt operatori binari. Expresia x << i este echivalentă
cuexpresia x * 2i. De fapt acest operator elimină cei mai din stânga i biţi ai lui x şi adaugă
ladreapta i biţi 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 (împărţirea întreagă a lui x prin 2i). Operatorul
dedeplasare la dreapta elimină cei mai din dreapta i biţi ai lui x şi adaugă la stânga i biţi de 0.
Deexemplu, dacă x = 0000000000001110(2), atunci x >> 2 înseamnă 0000000000000011(2)
= 3(adică 14 div 4).

 int n, masca;
n = 65 ;
masca = 100 ;
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 ;

 int count(long n)
{
int num = 0;
for (int i = 0;
i < 32; i++)
if (n & (1 << i)) num++;
return num;
}

 110111010100002 = n
110111010011112 = n – 1
110111010000002 = n & (n - 1)

 int parity(long n)
{
n = ((0xFFFF0000 & n) >> 16) ^ (n & 0xFFFF);
n = ((0xFF00 & n) >> 8) ^ (n & 0xFF);
n = ((0xF0 & n) >> 4) ^ (n & 0xF);
n = ((12 & n) >> 2) ^ (n & 3);
n = ((2 & n) >> 1) ^ (n & 1); return n;
}

 for (i= 3;i <=maxsize; i+= 2)


if (!at[((i - 3) >> 1) >> 8] & (1 << (((i - 3) >> 1) & 7)))
for (j = i * i ; j <= maxsize ; j += i + i)
at[((i - 3) >> 1) >> 8] |= (1 << (((i - 3) >> 1) & 7))) ;
}

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