--- title: Operatory bitowe slug: conflicting/Web/JavaScript/Reference/Operators tags: - JavaScript - Operator translation_of: Web/JavaScript/Reference/Operators translation_of_original: Web/JavaScript/Reference/Operators/Bitwise_Operators original_slug: Web/JavaScript/Referencje/Operatory/Bitwise_Operators ---
Operatory bitowe traktuję swoje operandy jako sekwencje 32 bitów (zer i jedynek), bardziej niż jako dziesiętne, szesnastkowe czy ósemkowe wartości liczbowe. Przykładowo, reprezentacją binarną dziesiętnej liczby 9 jest 1001. Operatory bitowe dokonują operacji na takich właśnie reprezentacjach bitowych, zwracają jednak standardowe JavaScriptowe wartości liczbowe.
Poniższa tabela zawiera podsumowanie operatorów bitowych w języku JavaScript:
| Operator | Użycie | Opis |
|---|---|---|
| Bitowe AND | a & b |
Zwraca 1 na każdej pozycji bitowej, dla której odpowiadające jej bity obydwu operandów mają wartość 1. |
| Bitowe OR | a | b |
Zwraca 1 na każdej pozycji bitowej, dla której jeden lub oba odpowiadające jej bity operandów mają wartość 1. |
| Bitowe XOR | a ^ b |
Zwraca 1 na każdej pozycji bitowej, dla której dokładnie jeden bit spośród odpowiadających jej bitów operandów ma wartość jeden. |
| Bitowe NOT | ~ a |
Neguje bity swojego operandu. |
| Przesunięcie w lewo | a << b |
Przesuwa a w binarnej reprezentacji o b bitów w lewo (gdzie b < 32), dodając zera z prawej strony. |
| Przesunięcie w prawo z propagacją znaku | a >> b |
Przesuwa a w binarnej reprezentacji o b bitów w prawo (gdzie b < 32), odrzucając b bitów z prawej strony. |
| Przesunięcie w prawo z dopełnieniem zerami | a >>> b |
Przesuwa a w binarnej reprezentacji o b bitów w prawo (gdzie b < 32), odrzucając b bitów z prawej strony i uzupełniając sekwencję zerami z lewej strony. |
Operandy wszystkich operatorów bitowych są konwertowane do 32-bitowych wartości całkowitych w dwójkowym kodzie uzupełnieniowym, z wyjątkiem przesunięcia w prawo z dopełnieniem zerami, które zwraca 32-bitową wartość całkowitą bez znaku. Dwójkowy kod uzupełnieniowy oznacza, że liczba przeciwna danej wartości (na przykład 5 i -5) ma wszystkie bity zanegowane w stosunku do tejże wartości (bitowe NOT liczby, znane również jako jedynkowe dopełnienie liczby) plus jeden. Przykładowo, dziesiętna liczba 314 ma następującą postać dwójkową:
00000000000000000000000100111010
Reprezentacja binarna ~314, czyli jedynkowe dopełnienie 314:
11111111111111111111111011000101
-314 ma ostatecznie następującą postać, będącą dwójkowym dopełnieniem 314:
11111111111111111111111011000110
Dopełnienie dwójkowe gwarantuje, że skrajny lewy bit będzie zerem dla liczby dodatniej i jedynką dla liczby ujemnej – bit ten zwany jest stąd bitem znaku.
Liczba 0 jest wartością całkowitą, złożoną w całości z bitów o wartości 0.
0 (base 10) = 00000000000000000000000000000000 (base 2)
Liczba -1 jest wartością całkowitą, złożoną z samych bitów o wartości 1.
-1 (base 10) = 11111111111111111111111111111111 (base 2)
Liczba -2147483648 (reprezentacja szesnastkowa: -0x80000000) jest wartością całkowitą, złożoną z samych bitów o wartości 0, z wyjątkiem pierwszego (znajdującego się najbardziej z lewej strony) bitu.
-2147483648 (base 10) = 10000000000000000000000000000000 (base 2)
Liczba 2147483647 (rprezentacja szesnastkowa: 0x7fffffff) jest wartością całkowitą, złożoną jedynie z bitów o wartości 1, z wyjątkiem pierwszego (skrajnie lewego) bitu.
2147483647 (base 10) = 01111111111111111111111111111111 (base 2)
Liczby -2147483648 i 2147483647 stanowią odpowiednio minimalną i maksymalną wartość całkowitą, którą można zapisać przy użyciu 32-bitowej liczby ze znakiem.
Idea działania bitowych operatorów logicznych jest następująca:
Przed: 11100110111110100000000000000110000000000001 Po: 10100000000000000110000000000001
Stosuje operację AND (koniunkcję) na każdej parze bitów. a AND b daje 1 wtedy i tylko wtedy, gdy zarówno a, jak i b będą miały wartość 1. Tablica prawdy dla operacji AND przedstawiona jest poniżej:
| a | b | a AND b |
| 0 | 0 | 0 |
| 0 | 1 | 0 |
| 1 | 0 | 0 |
| 1 | 1 | 1 |
. 9 (base 10) = 00000000000000000000000000001001 (base 2)
14 (base 10) = 00000000000000000000000000001110 (base 2)
--------------------------------
14 & 9 (base 10) = 00000000000000000000000000001000 (base 2) = 8 (base 10)
Bitowa koniunkcja (AND) dowolnej wartości x i 0 zawsze daje 0.
Stosuje operację OR (alternatywę) na każdej parze bitów. a OR b daje 1 wtedy i tylko wtedy, gdy a lub b ma wartość 1. Tablica prawdy dla operacji OR przedstawina jest poniżej:
| a | b | a OR b |
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 1 |
. 9 (base 10) = 00000000000000000000000000001001 (base 2)
14 (base 10) = 00000000000000000000000000001110 (base 2)
--------------------------------
14 | 9 (base 10) = 00000000000000000000000000001111 (base 2) = 15 (base 10)
Zastosowanie alternatywy bitowej (OR) dowlonej wartości x i 0 zawsze daje x.
Stosuje bitowe XOR (alternatywę wykluczającą) na każdej parze bitów. a XOR b daje 1 wtedy i tylko wtedy, gdy a i b mają różne wartości. Tablica prawdy dla operacji XOR przedstawiona jest poniżej:
| a | b | a XOR b |
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 0 |
. 9 (base 10) = 00000000000000000000000000001001 (base 2)
14 (base 10) = 00000000000000000000000000001110 (base 2)
--------------------------------
14 ^ 9 (base 10) = 00000000000000000000000000000111 (base 2) = 7 (base 10)
Zastosowanie bitowej alternatywy wykluczającej (XOR) dowolnej wartości x i 0 daje x.
Stosuje operator NOT (negację) na każdym bicie. NOT a zwraca odwróconą wartość (inaczej zwaną dopełnieniem jedynkowym) a. Tablica prawdy operacji NOT przedstawiona jest poniżej:
| a | NOT a |
| 0 | 1 |
| 1 | 0 |
9 (base 10) = 00000000000000000000000000001001 (base 2)
--------------------------------
~9 (base 10) = 11111111111111111111111111110110 (base 2) = -10 (base 10)
Bitowa negacja (NOT) dowolnej wartości x daje -(x + 1). Przykładowo, ~-5 daje 4.
Zauważmy, że z powodu używania 32-bitowej reprezentacji liczb, zarówno ~-1, jak i ~4294967295 (232-1) daje wynik 0.
Bitowe operatory przesunięcia przyjmują dwa operandy: pierwszy jest wartością do przesunięcia, a drugi wskazuje liczbę pozycji bitowych, o którą pierszy operand ma być przesunięty. Kierunek operacji przesunięcia jest zdefiniowany przez użycie danego operatora.
Operatory przesunięcia konwertują swoje operandy do 32-bitowych wartości całkowitych w porządku big-endian (znanym też pod nazwą grubokońcowość) i zwraca wynik tego samego typu, co lewy operand. Użytych będzie przy tym jedynie pięć najniższych bitów prawego operandu.
Operator ten przesuwa pierwszy operand o określoną liczbę bitów w lewo. Nadmiarowe bity przesunięte poza zakres z lewej strony są odrzucane. Z prawej strony sekwencja uzupełniana jest zerami.
Przykładowo, 9 << 2 daje 36:
. 9 (base 10): 00000000000000000000000000001001 (base 2)
--------------------------------
9 << 2 (base 10): 00000000000000000000000000100100 (base 2) = 36 (base 10)
Bitowe przesuwanie dowolnej wartości x w lewo o y bitów daje x * 2 ** y.
Tak więc, przykładowo: 9 << 3 można przetłumaczyć jako: 9 * (2 ** 3) = 9 * (8) = 72.
Operator ten przesuwa pierwszy operand o określoną liczbę bitów w prawo. Nadmiarowe bity przesunięte z prawej strony poza zakres są odrzucane. Sekwencja jest uzupełniana z lewej strony wartościami skrajnie lewego bitu. Kiedy skrajnie lewy bit ma taką samą wartość, jak poprzedni skrajnie lewy bit, znak się nie zmienia – stąd nazwa „z propagacją znaku”.
Przykładowo, 9 >> 2 daje 2:
. 9 (base 10): 00000000000000000000000000001001 (base 2)
--------------------------------
9 >> 2 (base 10): 00000000000000000000000000000010 (base 2) = 2 (base 10)
Podobnie, -9 >> 2 daje -3, ponieważ zachowywany jest znak:
. -9 (base 10): 11111111111111111111111111110111 (base 2)
--------------------------------
-9 >> 2 (base 10): 11111111111111111111111111111101 (base 2) = -3 (base 10)
Operator ten przesuwa pierwszy operand o określoną liczbę bitów w prawo. Nadmiarowe bity przesunięte poza zakres z prawej strony są odrzucane. Sekwencja jest uzupełniana z lewej strony zerami. Bit znaku staje się zerem, dlatego też wynik jest zawsze nieujemny. W przeciwieństwie do pozostałych operatorów bitowych, przesunięcie w prawo z dopełnieniem zerami zwraca 32-bitową wartość całkowitą bez znaku.
Dla liczb nieujemnych, przesunięcie w prawo z zerami i z zachowaniem znaku dają taki sam wynik. Przykładowo, 9 >>> 2 daje 2, tak samo jak 9 >> 2:
. 9 (base 10): 00000000000000000000000000001001 (base 2)
--------------------------------
9 >>> 2 (base 10): 00000000000000000000000000000010 (base 2) = 2 (base 10)
Inaczej wygląda to jednak w przypadku liczb ujemnych. Przykładowo, -9 >>> 2 daje 1073741821, co jest różne od -9 >> 2 (które daje -3):
. -9 (base 10): 11111111111111111111111111110111 (base 2)
--------------------------------
-9 >>> 2 (base 10): 00111111111111111111111111111101 (base 2) = 1073741821 (base 10)
Bitowe operatory logiczne są często używane do tworzenia, manipulowania i odczytywania sekwencji flag, które działają jak zmienne binarne. Zmienne mogą być używane zamiast tych sekwencji, ale flagi zajmują znacznie mniej pamięci (32-krotnie).
Załóżmy, że mamy następujące 4 flagi:
Flagi te są reprezentowane przez sekwencję bitów: DCBA. Kiedy flaga jest ustawiona, odpowiedni bit ma wartość 1. Kiedy flaga jest wyczyszczona, właściwy bit ma wartość 0. Załóżmy, że zmienna flagi ma binarną wartość 0101:
var flagi = 5; // binarnie 0101
Wartość ta wskazuje, że:
Ponieważ operatory bitowe są 32-bitowe, 0101 to faktycznie 00000000000000000000000000000101, ale zera wiodące mogą być pominięte, gdyż nie zawierają żadnej znaczącej informacji.
Maska bitowa jest sekwencją bitów pozwalającą na manipulowanie flagami lub odczytywanie ich wartości. Zazwyczaj „podstawowe” maski bitowe dla każdej flagi będą zdefiniowane w następujący sposób:
var FLAGA_A = 1; // 0001 var FLAGA_B = 2; // 0010 var FLAGA_C = 4; // 0100 var FLAGA_D = 8; // 1000
Nowe maski bitowe mogą być stworzone przy użyciu operatorów bitowych na tychże podstawowych maskach. Przykładowo, maska 1011 może być stworzona przy użyciu operatora OR na zmiennych FLAGA_A, FLAGA_B i FLAGA_D.
var maska = FLAGA_A | FLAGA_B | FLAGA_D; // 0001 | 0010 | 1000 => 1011
Pojedyncze wartości flag mogą być wyekstrahowane przez użycie operatora AND na fladze i właściwej masce – bit z wartością 1 „ekstrahuje” odpowiednią flagę. Maska bitowa maskuje wszystkie nieistotne flagi przez koniunkcję ich bitów z zerami maski (stąd nazwa „maska”). Przykładowo, maska 0100 może być użyta do sprawdzenia, czy flaga C jest ustawiona:
// czy mamy kota
if (flagi & FLAGA_C) { // 0101 & 0100 => 0100 => true
// coś zrób
}
Maska z ustawionymi wieloma flagami działa jak alternatywa logiczna. Przykładowo, poniższe dwie wersje są równoważne:
// czy mamy nietoperza lub czy mamy kota
// (0101 & 0010) || (0101 & 0100) => 0000 || 0100 => true
if ((flagi & FLAGA_B) || (flagi & FLAGA_C)) {
// coś zrób
}
// czy mamy nietoperza lub kota
var maska = FLAGA_B | FLAGA_C; // 0010 | 0100 => 0110
if (flagi & maska) { // 0101 & 0110 => 0100 => true
// coś zrób
}
Flagi mogą być ustawione przez użycie na nich i masce operacji OR, gdzie każdy z bitów z wartością 1 będzie ustawiał odpowiednią flagę, jeśli nie jest już ustawiona. Przykładowo, maska 1100 może być użyta do ustawienia flag C i D:
// tak, możemy mieć kota i kaczkę var maska = FLAGA_C | FLAGA_D; // 0100 | 1000 => 1100 flagi |= maska; // 0101 | 1100 => 1101
Flagi mogą być czyszczone przez użycie operatora AND z maską, gdzie każdy z bitów z wartością 0 będzie czyścił odpowiednią flagę, jeśli nie jest już wyczyszczona. Maska może być stworzona przez użycie operatora NOT na maskach podstawowych. Przykładowo, maska 1010 może być użyta do wyczyszczenia flag A i C:
// nieprawdą jest, że mamy problem z mrówkami lub posiadamy kota var maska = ~(FLAG_A | FLAG_C); // ~0101 => 1010 flagi &= maska; // 1101 & 1010 => 1000
Maska może być również stworzona przez wyrażenie ~FLAG_A & ~FLAG_C (z praw De Morgana):
// nie, nie mamy problemu z mrówkami i nie posiadamy kota var maska = ~FLAGA_A & ~FLAGA_C; flagi &= maska; // 1101 & 1010 => 1000
Flagi mogą być przełączane przez użycie operatora XOR z maską bitową, gdzie każðy bit będzie przełączał odpowiednią flagę. Przykładowo, maska 0110 może być użyta do przełączenia flag B i C:
// jeśli nie mieliśmy nietoperza, teraz go mamy, // a jeśli go mieliśmy – pa, pa, nietoperku! // tak samo z kotami var maska = FLAGA_B | FLAGA_C; flagi = flagi ^ maska; // 1100 ^ 0110 => 1010
Flagi mogą być odwracane przez operator NOT:
// przechodzimy do równoległego wszechświata... flagi = ~flagi; // ~1010 => 0101
Konwersja binarnej zmiennej typu String do liczby dziesiętnej typu Number:
var sBinString = '1011'; var nMojaLiczba = parseInt(sBinString, 2); alert(nMojaLiczba); // wypisuje 11, tzn. binarnie 1011
Konwersja dziesiętnej liczby do binarnego Stringa:
var nMojaLiczba = 11; var sBinString = nMojaLiczba.toString(2); alert(sBinString); // wypisuje 1011, tzn. dziesiętnie 11
Możesz stworzyć wiele masek ze zbioru wartości typu Boolean values, na przykład:
function createMask() {
var nMask = 0, nFlag = 0, nLen = arguments.length > 32 ? 32 : arguments.length;
for (nFlag; nFlag < nLen; nMask |= arguments[nFlag] << nFlag++);
return nMask;
}
var mask1 = createMask(true, true, false, true); // 11, i.e.: 1011
var mask2 = createMask(false, false, true); // 4, i.e.: 0100
var mask3 = createMask(true); // 1, i.e.: 0001
// itd.
alert(mask1); // wypisuje 11, czyli binarnie: 1011
Jeśli chcesz stworzyć tablicę złożoną ze zmiennych boolowskich, możesz użyć następującego kodu:
function arrayFromMask(nMask) {
// nMask musi być pomiędzy -2147483648 a 2147483647
if (nMask > 0x7fffffff || nMask < -0x80000000) {
throw new TypeError('arrayFromMask - out of range');
}
for (var nShifted = nMask, aFromMask = []; nShifted;
aFromMask.push(Boolean(nShifted & 1)), nShifted >>>= 1);
return aFromMask;
}
var array1 = arrayFromMask(11);
var array2 = arrayFromMask(4);
var array3 = arrayFromMask(1);
alert('[' + array1.join(', ') + ']');
// wypisuje "[true, true, false, true]", tzn.: 11, tzn.: 1011
Możesz przetestować obydwa algorytmy naraz:
var nTest = 19; // nasza maska var nResult = createMask.apply(this, arrayFromMask(nTest)); alert(nResult); // 19
Jedynie dla celów dydaktycznych (jako że istnieje metoda Number.toString(2)), pokażemy jak można zmodyfikować algorytm arrayFromMask tak, by tworzył zmienną String zawierającą binarną reprezentację danej liczby, zamiast tablicy zmiennych typu Boolean:
function createBinaryString(nMask) {
// nMask musi być pomiędzy -2147483648 a 2147483647
for (var nFlag = 0, nShifted = nMask, sMask = ''; nFlag < 32;
nFlag++, sMask += String(nShifted >>> 31), nShifted <<= 1);
return sMask;
}
var string1 = createBinaryString(11);
var string2 = createBinaryString(4);
var string3 = createBinaryString(1);
alert(string1);
// wypisuje 00000000000000000000000000001011, i.e. 11
| Specyfikacja | Status | Komentarz |
|---|---|---|
| {{SpecName('ES1')}} | {{Spec2('ES1')}} | Definicja początkowa. |
| {{SpecName('ES5.1', '#sec-11.7')}} | {{Spec2('ES5.1')}} | Zdefiniowane w kilku sekcjach specyfikacji: Bitwise NOT operator, Bitwise shift operators, Binary bitwise operators |
| {{SpecName('ES6', '#sec-bitwise-shift-operators')}} | {{Spec2('ES6')}} | Zdefiniowane w kilku sekcjach specyfikacji: Bitwise NOT operator, Bitwise shift operators, Binary bitwise operators |
| {{SpecName('ESDraft', '#sec-bitwise-shift-operators')}} | {{Spec2('ESDraft')}} | Zdefiniowane w kilku sekcjach specyfikacji: Bitwise NOT operator, Bitwise shift operators, Binary bitwise operators |
The compatibility table on this page is generated from structured data. If you'd like to contribute to the data, please check out https://github.com/mdn/browser-compat-data and send us a pull request.
{{Compat("javascript.operators.bitwise")}}