"Cześć, Amigo!"

„Chciałbym też porozmawiać o maskach bitowych i XOR”.

„Wiesz już, że liczby składają się z bitów i możesz wykonywać na nich różne operacje. Maska bitowa to reprezentacja kilku różnych wartości logicznych (wartości prawda/fałsz) jako pojedyncza liczba całkowita. W tym przypadku każda wartość logiczna odpowiada określony bit. Oto jak można to zrobić:

„Dwójkowa reprezentacja potęg dwójki (1, 2, 4, 8, 16, 32,…) wymaga ustawienia tylko jednego bitu:”

Numer Reprezentacja binarna
1 0000 0001
2 0000 0010
4 0000 0100
8 0000 1000
16 0001 0000
19 (nie potęga dwójki) 0001 0011
31 (nie potęga dwójki) 0001 1111

„Tak więc każdą liczbę całkowitą można traktować jako tablicę bitów lub tablicę wartości logicznych”.

„Oto, jak możesz przechowywać różne wartości logiczne w jednej liczbie:”

Wartości logiczne
boolean a = true;
boolean b = false;
boolean c = true;
boolean d = false;
Wartości spakowane w jedną liczbę:
int result = 0;
 if (a) result += 1; // 1 == 20 — bit 0
 if (b) result += 2; // 2 == 21 — bit 1
 if (c) result += 4; // 4 == 22 — bit 2
 if (d) result += 8; // 8 == 23 — bit 3

„Teraz każdy bit ma wartość 1, jeśli odpowiadająca mu zmienna boolowska była prawdziwa”.

W naszym przypadku zmienne a i c były prawdziwe, więc wynik jest równy 1+4 == 5

0000 0101
0000 dcba

– Chyba wiem, co się dzieje.

- Cóż, jeśli rozumiesz, przejdźmy dalej.

„Int ma 32 bity. Jeden z nich jest używany jako znak liczby, a pozostałe 31 może służyć do przechowywania wartości 31 zmiennych boolowskich”.

„Long ma 64 bity, w których możemy przechowywać 63 zmienne boolowskie”.

"Tak."

„Dziesiątki zmiennych upchniętych w jedną liczbę. To całkiem sporo”.

„Ale gdzie to się stosuje?”

„Głównie w sytuacjach, w których trzeba przechowywać wiele informacji o obiektach. Kiedy przechowuje się wiele informacji o obiekcie, zawsze istnieje kilkadziesiąt zmiennych boolowskich. „Dzięki temu podejściu wszystkie są wygodnie przechowywane w jednej liczbie ”.

„Z naciskiem na słowo „przechowywane”. Ponieważ w rzeczywistości używanie numeru nie jest takie wygodne”.

„Nawiasem mówiąc, właśnie o to chciałem zapytać. Jak wyodrębnić wartość logiczną z liczby?”

„To wcale nie jest skomplikowane. Powiedzmy, że musisz ustalić, czy bit 6 jest ustawiony na 1 (2 do potęgi piątej to 32). Możemy to sprawdzić w ten sposób:”

Połącz liczby w jedną:
int a = 32; // 25 == 0010 0000
int b = 8; // 23 == 0000 1000
int c = 2; // 21 == 0000 0010

int result = a + b + c; // 32 + 8 + 2 == 42 == 0010 1010
Wyodrębnij wartości, sprawdzając określone bity:
int a = result & 32; // 0010 1010 & 0010 0000 = 0010 0000
int b = result & 8; // 0010 1010 & 0000 1000 = 0000 1000
int c = result & 2; // 0010 1010 & 0000 0010 = 0000 0010

„Tak więc praca z maskami bitowymi obejmuje trzy operacje:”

1)  Ustaw określony bit na 0

2)  Ustaw określony bit na 1

3)  Sprawdź wartość określonego bitu.

„Weź na przykład bit 6”.

„Jak ustawić bit 6 na 1?”

Kod Opis
result = result | 01000000;
result |= 01000000;
Jak ustawić bit 6 na 1?
result = result & 10111111;
result &= 10111111;
Jak ustawić bit 6 na 0?
c = result & 01000000;
Jak uzyskać wartość bitu 6?

„To bardzo niezwykłe, ale nie trudne. Człowieku, teraz jestem zapalonym programistą”.

„I jeszcze jedna mała wskazówka, jak łatwo uzyskać liczby z określonym bitem ustawionym na 0 lub 1: 01000000 lub 10111111”.

W tym celu mamy  operatory >> << .

„1 to 2 do potęgi zerowej. Innymi słowy, liczba z bitem 0 ustawionym na 1. Potrzebujemy liczby z bitem 6 ustawionym”.

int c = 1 << 6; // 0000 0001 << 6 == 0100 0000 == 64

„Świetnie! To naprawdę pomaga w takich przypadkach”.

„Ale co, jeśli potrzebuję liczby, w której każdy bit jest ustawiony na 1, z wyjątkiem jednego konkretnego bitu ustawionego na 0?”

"To też nie jest trudne:"

int d = ~(1 << 6); // ~0100 0000 == 10111111

„Innymi słowy, wszystko jest bardzo proste:”

Kod Opis
result = result | (1 << 6);
result |= (1 << 6);
Jak ustawić bit 6 na 1?
result = result & ~(1 << 6);
result &= ~(1 << 6);
Jak ustawić bit 6 na 0?
c = result & (1 << 6);
Jak uzyskać wartość bitu 6?

„To nie wygląda na bardzo trudne. Ale nie zapamiętam tego od razu”.

„Ale jeśli napotkasz przerażające wyrażenie, takie jak„ wynik &= ~(1 << 6) ”w czyimś kodzie, będziesz wiedział, że ten ktoś po prostu pracuje z maską bitową”.

„A jeśli często się z nim spotykasz, zapamięta się za ciebie”.

„Pamiętaj o sobie… To brzmi dobrze. Dziękuję za lekcję”.