Piszemy funkcję, która sprawdza, czy liczba jest nieparzysta używając operatorów bitowych. Do dzieła!

Na początek zobaczmy „normalną” funkcję isOdd:

const isOdd = (num) => num % 2 !== 0;

Sprawdzamy, czy reszta z dzielenia przez 2 jest nierówna 0. A w bitach jak to zrobimy?

W ogóle nie będziemy dzielić modulo ani w ten sposób porównywać. Zdefiniujmy sobie jakie liczby mogą nieparzyste w dwójkowym:

Wagi:   ( 16 )  ( 8 ) ( 4 )  ( 2 )  ( 1 )
8:        0       1     0      0      0
9:        0       1     0      0      0
4:        0       0     1      0      0
5:        0       0     1      0      1
6:        0       0     1      1      0
7:        0       0     1      1      1
16:       1       0     0      0      0
17:       1       0     0      0      1

Jak widać nie ma fizycznej możliwości, aby liczba była nieparzysta i nie miała włączonego ostatniego bitu (pierwszego od prawej) z liczbą 1. Bo nie ma innej nieparzystej wagi poza 1.

Wiedząc to możemy poddać liczbę parzystą i nieparzystą operatorowi & (bitwise and) na maskę 1. Zobaczmy jak to działa:

                 ( 8 ) ( 4 )  ( 2 )  ( 1 )
Liczba 8:          1     0      0      0
Maska 1:           0     0      0      1
Liczba & maska:    ---------------------- 8 & 1
Wynik              0     0      0      0  0
               

Aha, czyli liczba parzysta da nam 0. A nieparzysta?

                 ( 8 ) ( 4 )  ( 2 )  ( 1 )
Liczba 9:          1     0      0      1
Maska 1:           0     0      0      1
Liczba & maska:    ---------------------- 9 & 1
Wynik              0     0      0      1  1

Dobra, zatem nasza funkcja będzie wyglądać tak:

const isOddBitwise = (num) => num & 1;

Oczywiście logika bitowa jest tak trudna i dziwna dla nas, że musimy pamiętać, aby wszystko testować, wrzucać w pętle, to nie jest takie proste jak przeczytać zasadę matematyczną, użyć operatora matematycznego i już, gotowe.

To jest, możemy zastosować dzielenie modulo i porównywanie za pomocą bitowych, ale chyba to jeszcze nie ten level. My tego nie robimy, ani bitowymi, ani tym bardziej normalnymi operatorami. Nie muszę dodawać, że operatory bitowe są dużo szybsze i & 1 też jest szybsze, niż modulo.

Oczywiście z perspektywy zamieniania w JS modulo na & 1 to nie jest żadna optymalizacja zaś poważne utrudnienie dla czytelności, ale historia zna przypadki, gdzie umiejętne stosowanie operatorów bitowych było bardzo korzystne. Nie nauczymy się ich nigdy z nich nie korzystając.

Następna lekcja – isEvenBitwise…