Bitwise operators

This translation is incomplete. Please help translate this article from English

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.

The following table summarizes JavaScript's bitwise operators:

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.

32-bitowe wartości całkowite ze znakiem

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.

Bitowe operatory logiczne

Idea działania bitowych operatorów logicznych jest następująca:

  • Operandy są konwertowane do 32-bitowych wartości całkowitych, wyrażanych jako sekwencja bitów (zer i jedynek). Dla liczb o więcej niż 32 bitach odrzuca się najbardziej znaczące bity. Przykładowo, następująca wartość całkowita zajmująca więcej niż 32 bity będzie przekonwertowana do 32-bitowej wartości w następujący sposób:
    Przed: 11100110111110100000000000000110000000000001
    Po:                10100000000000000110000000000001
  • Każdy z bitów pierwszego operandu parowany jest z odpowiadającym mu bitem drugiego operandu: pierwszy z pierwszym, drugi z drugim i tak dalej (idąc od prawej strony).
  • Operator jest stosowany na każdej parze bitów, a wynik jest tworzony bitowo.

& (Bitowe AND)

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.

| (Bitowe OR)

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.

^ (Bitowe XOR)

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.

~ (Bitowe NOT)

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

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.

<< (Przesunięcie w lewo)

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.

>> (Przesunięcie w prawo z propagacją znaku)

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)

>>> (Przesunięcie w prawo z dopełnieniem zerami)

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)

Przykłady

Flagi i maski bitowe

The bitwise logical operators are often used to create, manipulate, and read sequences of flags, which are like binary variables. Variables could be used instead of these sequences, but binary flags take much less memory (by a factor of 32).

Suppose there are 4 flags:

  • flag A: we have an ant problem
  • flag B: we own a bat
  • flag C: we own a cat
  • flag D: we own a duck

These flags are represented by a sequence of bits: DCBA. When a flag is set, it has a value of 1. When a flag is cleared, it has a value of 0. Suppose a variable flags has the binary value 0101:

var flags = 5;   // binary 0101

This value indicates:

  • flag A is true (we have an ant problem);
  • flag B is false (we don't own a bat);
  • flag C is true (we own a cat);
  • flag D is false (we don't own a duck);

Since bitwise operators are 32-bit, 0101 is actually 00000000000000000000000000000101, but the preceding zeroes can be neglected since they contain no meaningful information.

A bitmask is a sequence of bits that can manipulate and/or read flags. Typically, a "primitive" bitmask for each flag is defined:

var FLAG_A = 1; // 0001
var FLAG_B = 2; // 0010
var FLAG_C = 4; // 0100
var FLAG_D = 8; // 1000

New bitmasks can be created by using the bitwise logical operators on these primitive bitmasks. For example, the bitmask 1011 can be created by ORing FLAG_A, FLAG_B, and FLAG_D:

var mask = FLAG_A | FLAG_B | FLAG_D; // 0001 | 0010 | 1000 => 1011

Individual flag values can be extracted by ANDing them with a bitmask, where each bit with the value of one will "extract" the corresponding flag. The bitmask masks out the non-relevant flags by ANDing with zeroes (hence the term "bitmask"). For example, the bitmask 0100 can be used to see if flag C is set:

// if we own a cat
if (flags & FLAG_C) { // 0101 & 0100 => 0100 => true
   // do stuff
}

A bitmask with multiple set flags acts like an "either/or". For example, the following two are equivalent:

// if we own a bat or we own a cat
// (0101 & 0010) || (0101 & 0100) => 0000 || 0100 => true
if ((flags & FLAG_B) || (flags & FLAG_C)) {
   // do stuff
}
// if we own a bat or cat
var mask = FLAG_B | FLAG_C; // 0010 | 0100 => 0110
if (flags & mask) { // 0101 & 0110 => 0100 => true
   // do stuff
}

Flags can be set by ORing them with a bitmask, where each bit with the value one will set the corresponding flag, if that flag isn't already set. For example, the bitmask 1100 can be used to set flags C and D:

// yes, we own a cat and a duck
var mask = FLAG_C | FLAG_D; // 0100 | 1000 => 1100
flags |= mask;   // 0101 | 1100 => 1101

Flags can be cleared by ANDing them with a bitmask, where each bit with the value zero will clear the corresponding flag, if it isn't already cleared. This bitmask can be created by NOTing primitive bitmasks. For example, the bitmask 1010 can be used to clear flags A and C:

// no, we don't have an ant problem or own a cat
var mask = ~(FLAG_A | FLAG_C); // ~0101 => 1010
flags &= mask;   // 1101 & 1010 => 1000

The mask could also have been created with ~FLAG_A & ~FLAG_C (De Morgan's law):

// no, we don't have an ant problem, and we don't own a cat
var mask = ~FLAG_A & ~FLAG_C;
flags &= mask;   // 1101 & 1010 => 1000

Flags can be toggled by XORing them with a bitmask, where each bit with the value one will toggle the corresponding flag. For example, the bitmask 0110 can be used to toggle flags B and C:

// if we didn't have a bat, we have one now, 
// and if we did have one, bye-bye bat
// same thing for cats
var mask = FLAG_B | FLAG_C;
flags = flags ^ mask;   // 1100 ^ 0110 => 1010

Finally, the flags can all be flipped with the NOT operator:

// entering parallel universe...
flags = ~flags;    // ~1010 => 0101

Conversion snippets

Convert a binary String to a decimal Number:

var sBinString = '1011';
var nMyNumber = parseInt(sBinString, 2);
alert(nMyNumber); // prints 11, i.e. 1011

Convert a decimal Number to a binary String:

var nMyNumber = 11;
var sBinString = nMyNumber.toString(2);
alert(sBinString); // prints 1011, i.e. 11

Automate Mask Creation

You can create multiple masks from a set of Boolean values, like this:

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
// etc.

alert(mask1); // prints 11, i.e.: 1011

Reverse algorithm: an array of booleans from a mask

If you want to create an Array of Booleans from a mask you can use this code:

function arrayFromMask(nMask) {
  // nMask must be between -2147483648 and 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(', ') + ']');
// prints "[true, true, false, true]", i.e.: 11, i.e.: 1011

You can test both algorithms at the same time…

var nTest = 19; // our custom mask
var nResult = createMask.apply(this, arrayFromMask(nTest));

alert(nResult); // 19

For the didactic purpose only (since there is the Number.toString(2) method), we show how it is possible to modify the arrayFromMask algorithm in order to create a String containing the binary representation of a Number, rather than an Array of Booleans:

function createBinaryString(nMask) {
  // nMask must be between -2147483648 and 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);
// prints 00000000000000000000000000001011, i.e. 11

Specyfikacje

Specyfikacja Status Komentarz
ECMAScript 1st Edition (ECMA-262) Standard Definicja początkowa.
ECMAScript 5.1 (ECMA-262) Standard Zdefiniowane w kilku sekcjach specyfikacji: Bitwise NOT operator, Bitwise shift operators, Binary bitwise operators
ECMAScript 2015 (6th Edition, ECMA-262) Standard Zdefiniowane w kilku sekcjach specyfikacji: Bitwise NOT operator, Bitwise shift operators, Binary bitwise operators
ECMAScript Latest Draft (ECMA-262) Draft Zdefiniowane w kilku sekcjach specyfikacji: Bitwise NOT operator, Bitwise shift operators, Binary bitwise operators

Wsparcie przeglądarek

Update compatibility data on GitHub
DesktopMobileServer
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewChrome for AndroidFirefox for AndroidOpera for AndroidSafari on iOSSamsung InternetNode.js
Bitwise AND (a & b)Chrome Full support 1Edge Full support 12Firefox Full support 1IE Full support 3Opera Full support YesSafari Full support YesWebView Android Full support 1Chrome Android Full support 18Firefox Android Full support 4Opera Android Full support YesSafari iOS Full support YesSamsung Internet Android Full support 1.0nodejs Full support Yes
Bitwise left shift (a << b)Chrome Full support 1Edge Full support 12Firefox Full support 1IE Full support 3Opera Full support YesSafari Full support YesWebView Android Full support 1Chrome Android Full support 18Firefox Android Full support 4Opera Android Full support YesSafari iOS Full support YesSamsung Internet Android Full support 1.0nodejs Full support Yes
Bitwise NOT (~a)Chrome Full support 1Edge Full support 12Firefox Full support 1IE Full support 3Opera Full support YesSafari Full support YesWebView Android Full support 1Chrome Android Full support 18Firefox Android Full support 4Opera Android Full support YesSafari iOS Full support YesSamsung Internet Android Full support 1.0nodejs Full support Yes
Bitwise OR (a | b)Chrome Full support 1Edge Full support 12Firefox Full support 1IE Full support 3Opera Full support YesSafari Full support YesWebView Android Full support 1Chrome Android Full support 18Firefox Android Full support 4Opera Android Full support YesSafari iOS Full support YesSamsung Internet Android Full support 1.0nodejs Full support Yes
Bitwise right shift (a >> b)Chrome Full support 1Edge Full support 12Firefox Full support 1IE Full support 3Opera Full support YesSafari Full support YesWebView Android Full support 1Chrome Android Full support 18Firefox Android Full support 4Opera Android Full support YesSafari iOS Full support YesSamsung Internet Android Full support 1.0nodejs Full support Yes
Bitwise unsigned right shift (a >>> b)Chrome Full support 1Edge Full support 12Firefox Full support 1IE Full support 3Opera Full support YesSafari Full support YesWebView Android Full support 1Chrome Android Full support 18Firefox Android Full support 4Opera Android Full support YesSafari iOS Full support YesSamsung Internet Android Full support 1.0nodejs Full support Yes
Bitwise XOR (a ^ b)Chrome Full support 1Edge Full support 12Firefox Full support 1IE Full support 3Opera Full support YesSafari Full support YesWebView Android Full support 1Chrome Android Full support 18Firefox Android Full support 4Opera Android Full support YesSafari iOS Full support YesSamsung Internet Android Full support 1.0nodejs Full support Yes

Legend

Full support  
Full support

Zobacz też