Już teraz chyba uda nam się napisać operację dodawania za pomocą operatorów bitowych. Jeszcze raz przeróbmy poprzednie lekcje i zastanówmy się jak ma to wyglądać!
Ok, dodamy sobie dwie liczby wyszczególniając w pamięci oraz cyfrę:
w pamięci | 1 | 1 | - | - |
x | 0 | 0 | 1 | 1 | (3)
y | 0 | 1 | 1 | 0 | (6)
--------------------------------------
suma | 1 | 0 | 0 | 1 | (9)
Jak widać :
- 1 + 0, cyfra 0, w pamięci 0
- 1 + 1, cyfra 0, w pamięci 1
- 1 + 0 i 1 w pamięci – cyfra 0, 1 w pamięci
- 0 + 0 i 1 w pamięci – cyfra 1, 0 w pamięci
- 0 w pamięci bo 0 & 0 << 1 daje 0, wyjście z pętli
Lepiej tego wyjaśnić nie potrafię. Możemy jeszcze przejść się po kodzie:
function bitwiseAddNumbers(x, y){
while(y !== 0){
let carry = x & y;
x = x ^ y;
y = carry << 1;
}
return x;
}
console.log(bitwiseAddNumbers(4, 4));//8
console.log(bitwiseAddNumbers(5, 3));//8
console.log(bitwiseAddNumbers(3, 2));//5
Wygląda to tak:
- Jak y to zero to zwróć x (ma to sens, 2 + 0 to 2)
- Wylicz w pamięci – tylko 1 & 1 daje 1 w pamięci
- Wylicz pod x wartość z dodania cyfr – 1 ^ 1 da 0, 0 ^ 0 da 0, 0 ^ 1 da 1
- Wylicz następny y, czyli:
- Jeżeli 1 + 1, to (1 & 1) << 1 daje 2, wartość się zgadza tego co w pamięci
- Jeżeli gdzieś mamy już 0, to 0 & 0 << 1 daje 0 i wychodzimy z pętli
- Algorytm tak sprytnie zaplanowany, że pod x mamy wyliczoną wartość i jeśli to, co w pamięci, zostało, to też jest dodane
Dodajmy 5 + 5 i sprawdźmy, czy rozumiemy:
8 4 2 1
0 1 0 1
0 1 0 1
--------
1 0 1 0
To po prostu trzeba sobie na spokojnie analizować aż zrozumiemy…
Jeszcze raz, teraz na pełnych liczbach nie cyfrach, co 5 + 5 oznacza względem naszego algorytmu:
5 + 5
x = 5, y = 5
algorytm:
tak długo jak y !== 0
carry - x & y
x - x ^ y
y - carry << 1
wykonanie dla 5 + 5
sprawdź, czy y !== 0 - nie jest, y to 5
carry - 5 & 5
0 1 0 1
0 1 0 1 &
-------
0 1 0 1 (5) <-- carry
x - 5 ^ 5
0 1 0 1
0 1 0 1 ^
--------
0 0 0 0 (0) <--- x
y = carry << 1
0 1 0 1 << 1
--------
1 0 1 0 (10)
sprawdź warunek
y !== 0
10 !== 0 - prawda
carry - 0 & 10 (0)
x - 0 ^ 10 (10)
y - 0 << 1 (0)
koniec pętli, zwróć x (10)
Tak to działa.