Coraz mniej czasu w ciągu dnia więc postanowiłem wziąć na klatę podobny temat, zbliżony do poprzedniego (poprzednio pisałem o przesunięciach bitowych). Mają ze sobą wiele wspólnego (przesunięcia to jeden z typów) więc postanowiłem "postawić" te wątki obok siebie. Przed Wami, następna opowieść o alternatywnych zapisach. W roli głównej, operatory bitowe, ale nie te, które już dobrze znacie.

OPERATORY BITOWE. TŁUMACZENIE W PIGUŁCE

Wyjaśnienia dzielą się na proste i szybkie oraz długie i naukowe. Są jeszcze takie, które się w ogóle nie nadają. W każdym razie, objaśnię ten temat trzymając się pierwszego wariantu (tutaj macie wariant numer dwa). Tak na poważnie przechodząc do tematu, nie będę się produkował na temat tych klasycznych operatorów jak negacja (!) czy koniunkcja (&&). Raczej skupię się na pojedynczym ampersandzie (&) oraz pojedynczej pionowej kresce (|). Oba te zapisy są obsługiwane przez niektóre języki wysokiego poziomu (na pewno C, C++, Java i C#) i służą do obliczania liczb w sposób binarny. Takie ładne terminy to "koniunkcja binarna" i "alternatywa binarna". Operatory bitowe posiadają również takie rodzaje. Pozwólcie, że po raz kolejny zaprezentuję przykłady.

KONIUNKCJA BITOWA

Oprócz dobrze znanej koniunkcji "zwykłej" w postaci dwóch ampersandów (&&) istnieje również odmiana zastosowania koniunkcji dla liczb binarnych, która zwraca liczbę binarną w wyniku zastosowania operatora AND dla podanych dwóch / więcej liczb binarnych pod kreską. Tak wygląda przykład:

Zakładając, że mamy liczbę 45 w systemie binarnym:

0 0 1 0 1 1 0 1

 

oraz drugą liczbę binarną jako 78:

0 1 0 0 1 1 1 0

To przy zastosowaniu koniunkcji binarnej wynik będzie równy 12. Dlaczego? Ponieważ porównujemy każdy bit od lewej do prawej i tam, gdzie w obu przypadkach występuje 1, zapisujemy 1 (przypadek, gdy wszystkie warunki są prawdziwe). W przeciwnym razie podajemy zero. Widzicie sami, że operatory bitowe nie kończą się jedynie na kilku podstawowych. Weźmy sobie te obie liczby pod kreską:

0 0 1 0 1 1 0 1
0 1 0 0 1 1 1 0
0 0 0 0 1 1 0 0


W tym momencie nic nie powinno budzić wątpliwości. Po porównaniu sobie wszystkich osobnych bitów pojedynczo łatwo zauważyć, że jedynki są tylko tam, gdzie w obu liczbach też występuje jedynka. Zatem po zamianie na system dziesiętny mamy 12. Dodam, że można wprowadzać wiele liczb niż dwie. Na przykład koniunkcja bitowa liczb 45, 78 oraz 105 wyjdzie osiem. Pokombinujcie sami jak to policzyć. W językach wysokiego poziomu, najczęstszym "znakiem rozpoznawczym" jest pojedynczy ampersand (&).

ALTERNATYWA BITOWA

Alternatywa binarna działa podobnie, tylko że teraz wykonujemy badanie typu OR (prawda, gdy co najmniej jeden z kilku warunków jest prawdziwy). Mamy ten sam zbiór liczb 45 i 78. Zatem alternatywa bitowa dla tych liczb będzie równa 111. Rozrysujmy to sobie jeszcze raz:

0 0 1 0 1 1 0 1
0 1 0 0 1 1 1 0
0 1 1 0 1 1 1 1

Zgodnie z alternatywą, wystarczy jeden warunek spełniony, aby zdanie było prawdziwe. Wniosek nasuwa się samoistnie. Znak pionowej kreski (|), tak rozpoznacie alternatywę bitową w kodzie (zazwyczaj).

NEGACJA BITOWA

Operatory bitowe "uzbrojone" są także w klasyczną negację. Negacja binarna to, jak łatwo się domyślić, przestawienie bitów na przeciwną wartość. Wszystkie jedynki są zerami, a zera...domyślcie się. To jest operator unarny, czyli wykonujący operacje na pojedynczym argumencie ("operandzie"). I tak biorąc sobie dla przykładu liczbę 83, wynikiem jej zanegowania będzie -84. Żeby zrozumieć skąd się wziął wynik, potrzebna jest wiedza o tak zwanym "bicie znaku". Bit znaku to jest ta cyferka występująca jako pierwsza, licząc od lewej strony. Normalnie bity oznaczają składniki sumy n-tej potęgi liczby 2. W przypadku, gdy bit znaku staje się "jedynką", oznaczać będzie ujemną wartość wynikową, a co za tym idzie, od sumy trzeba odjąć 2N. Ponieważ ZAWSZE jest odejmowany składnik o najwyższej wartości (najbardziej znaczący bit), to zawsze "przeskoczy" sumę składników dodatnich i stąd powstaje wartość ujemna. Zaprezentuję to na takim samym schemacie jak powyżej. Spójrzcie:

0 1 0 1 0 0 1 1
1 0 1 0 1 1 0 0

Jak wspomniałem, pierwszy bit od lewej to jest bit znaku. Liczba 83 jest dodatnia więc bit znaku jest ustawiony na zero. Kiedy zanegujemy liczbę 83, to w wyniku "przekręcenia" bitów na przeciwną wartość, poza resztą bitów "normalnych", bit znaku także posiada wartość 1. Celem przekonwertowania na system dziesiętny, późniejsze kalkulacje wyglądają w taki sposób:

-27 + 25 + 23 + 22 = -128 + 32 + 16 + 8 = -84

Negacja bitowa jest oznaczana na kilka sposobów, w zależności od języka programowania bo to może być pod postacią operatora albo funkcji. Jednakże najczęstszym symbolem jest znak tyldy (~).


Mamy następny temat załatwiony. Operatory bitowe, ale te mniej znane. Dodam, że języki obsługujące te operacje pozwalają na skrócony zapis (&=, |= itd.), taki sam jak przy wszystkich podstawowych operacjach. Zastosowanie w praktyce oprócz szpanu? Konfigurowanie aplikacji w postaci nakładania "maski bitowej" dla przykładu (tak się bardzo często robi w C++).

PODOBNE ARTYKUŁY