|
Operatory bitowe w C++ Operatory bitowe służą do wykonywania operacji na pojedynczych bitach. Często tworzy się z nich maskę bitową.
| Operator bitowy | Znaczenie | | & | Iloczyn bitowy | | | | Suma bitowa | | ^ | Różnica symetryczna XOR | | >> | Przesunięcie bitowe w prawo | | << | Przesunięcie bitowe w lewo | | ~ | Negacja |
Dla przykładu odczytujemy bajt a i sprawdzamy, czy jego czwarty bit jest ustawiony czy nie. BYTE a = "54"; int bit2 = a & 8;
Przesunięcie bitowe w prawo Przesunięcie bitowe w prawo odpowiada arytmetycznemu dzieleniu przez 2.Dzielenie to jest wykonywane bez reszty. void __fastcall TForm1::Button1Click(TObject *Sender) { int liczba = 87; int maska = 1; int wynik = liczba >> maska; Label1->Caption = wynik; } //zwróci wynik 43, bo 43 x 2 = 86; reszta 1 jest pomijana Aby zrozumieć przykład, przedstawmy liczbę 87 (dziesiętnie) w kodzie dwójkowym.Sposób konwersji z systemu dziesiętnego na dwójkowy jest opisany w tym serwisie. 87 dec = 1010111 bin bo 20 *1 + 21 *1 + 22 *1 + 24 *1 + 26 *1 = 1+2+4+16+64 = 87 Gdy przesuniemy całą liczbę w prawo, najstarszy bit przechodzi na miejsce przedostatniego, a najmłodszy bit jest usuwamy.Po przesunięciu o jeden w prawo otrzymamy: 0101011 bin = 20 *1 + 21 *1 + 23 *1 + 25 *1 = 1 + 2 + 8 + 32 = 43 Co zrobić, jeśli chcemy liczbę podzielić przez 4 a nie przez 2? Przesunięcie bitowe w prawo należy wykonać dwukrotnie.W kodzie C++ będzie to rozwiązane tak: void __fastcall TForm1::Button1Click(TObject *Sender) { int liczba = 87; int maska = 2; int wynik = liczba >> maska; Label1->Caption = wynik; } //da w wyniku 21, czyli 10101 bin Co w przypadku, gdybyśmy chcieli dzielić liczbę przez 3 albo inną nieparzystą liczbę? Tą metodą się nie da, bo system dwójkowy to system o podstawie dwa.Dzielić można liczby jedynie przez potęgi dwójki.
Przesunięcie bitowe w lewo Skoro przesunięcie bitowe w prawo odpowiadało arytmetycznemu dzieleniu przez dwa, przesunięcie bitowe w lewo odpowiada arytmetycznemu mnożeniu przez 2.Aby pomnożyć przez dwa należy użyć operatora << 1, aby pomnożyć przez 16 należy użyć operatora << 4.Dla wspomnianej wyżej liczby 87, po wykonaniu takiej oto operacji void __fastcall TForm1::Button2Click(TObject *Sender) { int liczba = Edit3->Text.ToIntDef(0); int maska = 1; //dla 1 mnozenie przez 2, dla 2 mnozenie przez 4 itd. int wynik = liczba << maska; Edit4->Text = wynik; } otrzymamy wynik 174, bo 87 * 2 = 174. Negacja bitowa Aby zrozumieć na czym polega negacja bitowa, najlepiej posłużyć się zapisem binarnym liczby.Przedstawmy najpierw kod odpowiedzialny za obliczanie negacji bitowej. void __fastcall TForm1::Button1Click(TObject *Sender) { int liczba = Edit7->Text.ToIntDef(0); int wynik = ~liczba; Edit8->Text = wynik; } Jeśli w pole Edit7 wprowadzimy liczbę 87, to w wyniku otrzymamy -88.Logiczne.Dlaczego tak jest, poniżej. | Wartość dziesiętna | Wartość binarna | | 87 | 01010111 | | -88 | (-1)0101000 |
Aby to zrozumieć, należy wiedzieć jak w notacji dwójkowej zapisywane są liczby ujemne.W tym wypadku waga najstarszego bitu jest mnożona x (-1).Tak więc ~5 = -6 bo: 5 dec = 00000101 bin 5 zanegowane = 11111010 bin 27 *(-1) + 26 + 25 + 24 + 23 + 21 = -6 Liczba 13 da w wyniku negacji -14, liczba 1 da -2, liczba 0 da -1, liczba -5 da 4. Iloczyn bitowy W tej operacji mnożymy odpowiadające sobie bity liczby i maski bitowej.Liczba 87 rozbita na bity przedstawia się następująco: 1010111 bin, gdzie bit 6 = 1, bit 5 = 0, bit 4 = 1, bit 3 = 0, bit 2 = 1, bit 1 = 1, bit 0 = 1. Maska bitowa równa 8 dec rozbita na bity przedstawia się następująco: 1000 bin, gdzie bit 3 = 1, bit 2 = 0, bit 1 = 0, bit 0 = 0.Mnożymy przez siebie: bit 0 liczby x bit 0 maski, bit 1 liczby x bit 1 maski itd. Wiadomo, że: 0x0=0; 0x1=1x0=0; 1x1=1.To są własności operacji logicznej AND.Daje to w wyniku: bit wyniku 0: 1x0=0; bit wyniku 1: 1x0=0; bit wyniku 2: 1x0=0; bit wyniku 3: 0x1=0; bit wyniku 4: 1x0=0; bit wyniku 5: 0x0=0; bit wyniku 6: 1x0=0; bit wyniku 7: 0x0=0; A liczba o bitach 00000000 bin to właśnie 0 dec.Poniżej inne przykłady. Przykład 87 & 8 =0; 87 & 16 =16; 87 & 0 =0; 87 & 1 =1; 87 & 64 =64; 87 & 3 = 3; 87 & 12 = 87 & 4 = 4; Kod odpowiedzialny za wykonanie maski bitowej przedstawia się następująco: void __fastcall TForm1::Button4Click(TObject *Sender) { int liczba = Edit9->Text.ToIntDef(0); int maska = Edit10->Text.ToInt(); int wynik = liczba & maska; Label1->Caption = wynik; } Suma bitowa Jest to bardzo prosta operacja, polecająca na wykonaniu alternatywy.Mają tu zastosowanie własności alternatywy.Alternatywa odpowiada bramce logicznej OR. | Argument 1 | Argument 2 | Wynik alternatywy | | 0 | 1 | 1 | | 1 | 0 | 1 | | 0 | 0 | 0 | | 1 | 1 | 1 |
Jako przykład wykonamy operację 9 | 3. Liczba 9 przedstawiona binarnie daje 1001, a liczba 3 binarnie to 11.Tak więc dodajemy odpowiadające sobie bity liczby 1 oraz liczby 2.
bit wyniku 0: 1+1=1; bit wyniku 1: 0+1=1; bit wyniku 2: 0+0=0; bit wyniku 3: 1+0=1; W wyniku otrzymujemy liczbę 1101 bin, a więc 11. 9 | 3 = 11. Kod odpowiadający tej funkcji ma postać: void __fastcall TForm1::Button5Click(TObject *Sender) { int liczba1 = Edit11->Text.ToInt(); int liczba2 = Edit12->Text.ToInt(); int wynik = liczba1 | liczba2; Label2->Caption = wynik; } Różnica symetryczna XOR Funkcje logiczne mają swoje uzasadnienie w algebrze Boole'a.Funkcja różnicy symetrycznej nazywana jest także alternatywą wykluczającą i wynik jej jest prawdziwy, jeśli nieparzysta liczba argumentów jest prawdą.Poniżej tablica prawdy funkcji XOR. | Argument 1 | Argument 2 | Wynik exclusive or | | 0 | 0 | 0 | | 0 | 1 | 1 | | 1 | 0 | 1 | | 1 | 1 | 0 |
Jako przykład wykonamy działanie 3 XOR 8.Liczba 8 w postaci binarnej ma postać 1000.Liczba 3 binarnie wygląda następująco: 11. Wykonujemy operacje na odpowiadających sobie bitach:
bit wyniku 0: 0 XOR 1 = 1; bit wyniku 1: 0 XOR 1 = 1; bit wyniku 2: 0 XOR 0 = 0; bit wyniku 3: 1 XOR 0 = 1; Otrzymamy w wyniku liczbę 1 + 2*1 + 23 = 11.Tak więc 8 XOR 3 = 11.Inne przykłady: 8 XOR 2 = 10; 5 XOR 2 = 7; 5 XOR 5 = 0; 5 XOR 4 = 1; Pobierz projekt BCB z wszystkimi przykładami na operacjach bitowych.
|