Mozilla's getting a new look. What do you think? https://mzl.la/brandsurvey

ビット演算子

ビット演算子ではそのオペランドを 10 進数や 16 進数や 8 進数の数値ではなく、(0 や 1 が)32 ビットひと続きになったもの扱います。例えば、10 進数の 9 の 2 進表現は 1001 です。ビット演算子はこのように 2 進表現にした上で演算を行いますが、標準の JavaScript の数値を返します。

次の表で JavaScript のビット演算子について説明します:

演算子 使用方法 説明
ビットごとの AND a & b オペランドの対応するビットがともに 1 である各ビットについて 1 を返します。
ビットごとの OR a | b オペランドの対応するビットがどちらかまたはともに 1 である各ビットについて 1 を返します。
ビットごとの XOR a ^ b オペランドの対応するビットがどちらか一方のみ 1 である各ビットについて 1 を返します。
ビットごとの NOT ~ a オペランドの各ビットを反転します。
左シフト a << b 2 進表現の ab (< 32) ビット分だけ左にシフトします。右から 0 を詰めます。
符号を維持する右シフト a >> b 2 進表現の ab (< 32) ビット分だけ右にシフトします。あふれたビットは破棄します。
0 埋め右シフト a >>> b 2 進表現の ab (< 32) ビット分だけ右にシフトします。あふれたビットは破棄し、左から 0 を詰めます。

符号付き 32 ビット整数値

すべてのビット演算でオペランドは符号付き 32 ビット演算に、ビッグエンディアンおよび 2 の補数形式で変換されます。2 の補数形式では、ある値に対する負数 (例えば 5 と -5) は、正数のビットをすべて反転 (正数の NOT ビット演算、1 の補数として知られています) して 1 を加えたものになります。例えば以下は、整数値 314 (10 進数) を表しています:

00000000000000000000000100111010

以下は ~314、すなわち 314 の 1 の補数を表しています:

11111111111111111111111011000101

最後に、以下は -314、すなわち 314 の 2 の補数を表しています:

11111111111111111111111011000110

2 の補数では、左端のビットが 0 であれば数値は正数、1 であれば数値は負数であることを保証します。よって、そのビットは符号ビットと呼ばれます。

数値 0 は、すべてのビットが 0 で構成される整数です。

0 (10 進数) = 00000000000000000000000000000000 (2 進数)

数値 -1 は、すべてのビットが 1 で構成される整数です。

-1 (10 進数) = 11111111111111111111111111111111 (2 進数)

数値 -2147483648 (16 進表記: -0x80000000) は、最初 (左端) を除きすべてのビットが 0 で構成される整数です。

-2147483648 (10 進数) = 10000000000000000000000000000000 (2 進数)

数値 2147483647 (16 進表記: 0x7fffffff) は、最初 (左端) を除きすべてのビットが 1 で構成される整数です。

2147483647 (10 進数) = 01111111111111111111111111111111 (2 進数)

数値 -2147483648 および 2147483647 は、符号付き 32 ビット数値で表現できる最小および最大の整数です。

ビットごとの論理演算子

概念的にビットごとの論理演算子は、以下のように機能します:

  • オペランドは 32 ビット整数に変換され、ビット列(0 と 1)として表現されます。32 ビットを超える数値は、最上位のビットが破棄されます。例えば以下の 32 ビットを超える数値は、32 ビット整数値に変換されます:
    変換前: 11100110111110100000000000000110000000000001
    変換後:              10100000000000000110000000000001
  • 第 1 オペランドの各ビットは第 2 オペランドの対応するビットと対にされます。第 1 ビットと第 1 ビット、 第 2 ビットと第 2 ビット、というように対にされます。
  • 演算子は各ビットのペアに適用され、結果はビットごとに組み立てられます。

& (ビットごとの AND)

AND 演算は、ビットの各組で実行します。a AND b は、ab の両方が 1 である場合にのみ 1 を出力します。AND 演算の真理値表は以下のとおりです:

a b a AND b
0 0 0
0 1 0
1 0 0
1 1 1
.    9 (10 進数) = 00000000000000000000000000001001 (2 進数)
    14 (10 進数) = 00000000000000000000000000001110 (2 進数)
                   --------------------------------
14 & 9 (10 進数) = 00000000000000000000000000001000 (2 進数) = 8 (10 進数)

任意の数値 x と 0 とのビットごとの AND 演算は、0 を出力します。任意の数値 x と -1 とのビットごとの AND 演算は、x を出力します。

| (ビットごとの OR)

OR 演算は、ビットの各組で実行します。a OR b は、ab のいずれかが 1 である場合に 1 を出力します。OR 演算の真理値表は以下のとおりです:

a b a OR b
0 0 0
0 1 1
1 0 1
1 1 1
.    9 (10 進数) = 00000000000000000000000000001001 (2 進数)
    14 (10 進数) = 00000000000000000000000000001110 (2 進数)
                   --------------------------------
14 | 9 (10 進数) = 00000000000000000000000000001111 (2 進数) = 15 (10 進数)

任意の数値 x と 0 とのビットごとの OR 演算は、x を出力します。任意の数値 x と -1 とのビットごとの OR 演算は、-1 を出力します。

^ (ビットごとの XOR)

XOR 演算は、ビットの各組で実行します。a XOR b は、ab が異なる場合に 1 を出力します。XOR 演算の真理値表は以下のとおりです:

a b a XOR b
0 0 0
0 1 1
1 0 1
1 1 0
.    9 (10 進数) = 00000000000000000000000000001001 (2 進数)
    14 (10 進数) = 00000000000000000000000000001110 (2 進数)
                   --------------------------------
14 ^ 9 (10 進数) = 00000000000000000000000000000111 (2 進数) = 7 (10 進数)

任意の数値 x と 0 とのビットごとの XOR 演算は、x を出力します。任意の数値 x と -1 とのビットごとの XOR 演算は、~x を出力します。

~ (ビットごとの NOT)

NOT 演算は、各ビットで実行します。NOT a は、a を反転した値 (1 の補数として知られています) を出力します。NOT 演算の真理値表は以下のとおりです:

a NOT a
0 1
1 0
 9 (10 進数) = 00000000000000000000000000001001 (2 進数)
               --------------------------------
~9 (10 進数) = 11111111111111111111111111110110 (2 進数) = -10 (10 進数)

任意の数値 x のビットごとの NOT 演算は、-(x + 1) を出力します。例えば、~5 で -6 を出力します。

indexOf を使用する例:

var str = 'rawr';
var searchFor = 'a';

// これは (-1*str.indexOf('a') <= -1) の代替表記
if (~str.indexOf(searchFor)) {
  // searchFor が文字列内に存在する
} else {
  // searchFor が文字列内に存在しない
}

// (~str.indexOf(searchFor)) が返す値
// r == -1
// a == -2
// w == -3

ビットシフト演算子

ビットシフト演算子は 2 つのオペランドをとります。第 1 のオペランドはシフトされる数を指定し、第 2 のオペランドは、第 1 のオペランドをシフトさせるビット数を指定します。シフト演算の方向は使用する演算子によって決まります。

シフト演算子はそのオペランドをビッグエンディアン形式の 32 ビット整数に変換し、左のオペランドと同じ型の結果を返します。右のオペランドは 32 より小さくするべきであり、そうでない場合は下位 5 ビットのみが用いられます。

<< (左シフト)

この演算子は、第 1 オペランドを指定したビット数分だけ左にシフトします。左にあふれたビットは破棄されます。0 のビットを右から詰めます。

例えば、9 << 2 の結果は 36 になります。

.    9 (10 進数): 00000000000000000000000000001001 (2 進数)
                  --------------------------------
9 << 2 (10 進数): 00000000000000000000000000100100 (2 進数) = 36 (10 進数)

任意の数値 xy ビット左にシフトすると、x * 2^y になります。

>> (符号を維持する右シフト)

この演算子は、第 1 オペランドを指定したビット数分だけ右にシフトします。右にあふれたビットは破棄されます。左端のビットのコピーを左から詰めます。新たな左端のビットは従来の左端のビットと同じであることから、符号ビット (左端のビット) は変わりません。それゆえ、"符号を維持" という名称になります。

例えば、9 >> 2 の結果は 2 になります。

.    9 (10 進数): 00000000000000000000000000001001 (2 進数)
                  --------------------------------
9 >> 2 (10 進数): 00000000000000000000000000000010 (2 進数) = 2 (10 進数)

同様に、-9 >> 2 の結果は符号が維持されるため -3 になります:

.    -9 (10 進数): 11111111111111111111111111110111 (2 進数)
                   --------------------------------
-9 >> 2 (10 進数): 11111111111111111111111111111101 (2 進数) = -3 (10 進数)

>>> (0 埋め右シフト)

この演算子は、第 1 オペランドを指定したビット数分だけ右にシフトします。右にあふれたビットは破棄されます。0 のビットを左から詰めます。符号ビットが 0 になりますので、結果は常に負数になりません。

負数ではない値では、0 埋め右シフトと符号を維持した右シフトは同じ結果になります。例えば、9 >>> 2 の結果は 2 になり、9 >> 2 と同じです:

.     9 (10 進数): 00000000000000000000000000001001 (2 進数)
                   --------------------------------
9 >>> 2 (10 進数): 00000000000000000000000000000010 (2 進数) = 2 (10 進数)

しかし、これは負数に当てはまりません。例えば、-9 >>> 2 の結果は 1073741821 であり、-9 >> 2 の結果 (-3 になります) と異なります:

.     -9 (10 進数): 11111111111111111111111111110111 (2 進数)
                    --------------------------------
-9 >>> 2 (10 進数): 00111111111111111111111111111101 (2 進数) = 1073741821 (10 進数)

フラグとビットマスク

ビット論理演算子は、一連のフラグを作成、操作、あるいは読み取りによく用いられ、それらフラグはバイナリ変数のようなものです。変数は一連のフラグの代わりに用いられますが、バイナリフラグがもつメモリはとても少なく (32倍) なります。

4 つのフラグがあると仮定します:

  • フラグ A: 我々は蟻の問題を抱えています
  • フラグ B: 我々はコウモリを飼っています
  • フラグ C: 我々は猫を飼っています
  • フラグ D: 我々はアヒルを飼っています

これらのフラグは一連のビット DCBA で表されます。フラグがセットされると、それは値 1 になります。フラグがクリアされると、それは値 0 になります。変数 flags が 2 進数値 0101 であるとします:

var flags = 5;   // 2 進数値 0101

この値は以下を示します:

  • flag A は true (蟻の問題を抱えています);
  • flag B は false (コウモリを飼っていません);
  • flag C は true (猫を飼っています);
  • flag D は false (アヒルを飼っていません);

ビット演算は 32 ビットで行われることから、0101 は実際 00000000000000000000000000000101 ですが、先行する 0 は意味のある情報ではないため無視できます。

ビットマスク はフラグの操作や読み取りを可能にするビット列です。一般的に、各フラグ向けの "基本" ビットマスクが定義されます:

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

新たなビットマスクを、これら基本ビットマスクのビット論理演算を用いて作成できます。例えば、ビットマスク 1011 は FLAG_A、FLAG_B、FLAG_D の OR 演算により作成できます:

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

個々のフラグの値はビットマスクとの AND 演算によって抽出され、そのとき値 1 をもつ各ビットが対応するフラグを "抽出" します。ビットマスクは 0 との AND 演算により、関係のないフラグをマスクします (それゆえ、"ビットマスク" という用語になります)。例えば、ビットマスク 0100 はフラグ C がセットされているかの確認に用いることができます:

// 猫を飼っている場合
if (flags & FLAG_C) { // 0101 & 0100 => 0100 => true
   // さまざまな処理
}

複数のフラグをセットしたビットマスクは、"いずれか" を表します。例えば、以下 2 つの例は同等です:

// コウモリか猫を飼っている場合
// (0101 & 0010) || (0101 & 0100) => 0000 || 0100 => true
if ((flags & FLAG_B) || (flags & FLAG_C)) {
   // さまざまな処理
}
// コウモリか猫を飼っている場合
var mask = FLAG_B | FLAG_C; // 0010 | 0100 => 0110
if (flags & mask) { // 0101 & 0110 => 0100 => true
   // さまざまな処理
}

フラグはビットマスクとの OR 演算によって設定でき、値が 1 である各々のビットが対応するフラグを、まだセットされていない場合にセットします。例えば、ビットマスク 1100 はフラグ C と D のセットに用いることができます:

// はい、猫とアヒルを飼っています
var mask = FLAG_C | FLAG_D; // 0100 | 1000 => 1100
flags |= mask;   // 0101 | 1100 => 1101

フラグはビットマスクとの AND 演算によってクリアでき、値が 0 である各ビットが対応するフラグを、まだクリアされていない場合にクリアします。このビットマスクは、基本ビットマスクの NOT 演算で作成されます。例えば、ビットマスク 1010 はフラグ A と C のクリアに用いることができます:

// いいえ、蟻の問題はありませんし猫を飼ってもいません
var mask = ~(FLAG_A | FLAG_C); // ~0101 => 1010
flags &= mask;   // 1101 & 1010 => 1000

マスクは ~FLAG_A & ~FLAG_C (ド・モルガンの法則) で作成することもできます:

// いいえ、蟻の問題はありませんし猫を飼ってもいません
var mask = ~FLAG_A & ~FLAG_C;
flags &= mask;   // 1101 & 1010 => 1000

フラグはビットマスクとの XOR 演算によって切り替えることができ、値が 1 である各々のビットが対応するフラグを切り替えます。例えば、ビットマスク 0110 はフラグ B と C の切り替えに用いることができます:

// 以前はコウモリを飼っていませんでしたが今は飼っている、 
// および以前飼っていたコウモリとお別れした、
// また猫にも同じことが起きた場合
var mask = FLAG_B | FLAG_C;
flags = flags ^ mask;   // 1100 ^ 0110 => 1010

最後に、NOT 演算でフラグを反転することができます:

// パラレルワールドに入りました……
flags = ~flags;    // ~1010 => 0101

変換用コード部品

2 進数の String を 10 進数の Number に変換します:

var sBinString = "1011";
var nMyNumber = parseInt(sBinString, 2);
alert(nMyNumber); // 11 と表示、すなわち 1011

10 進数の Number を 2 進数の String に変換します:

var nMyNumber = 11;
var sBinString = nMyNumber.toString(2);
alert(sBinString); // 1011 と表示、すなわち 11

マスク作成の自動化

いくつかの Boolean から多くのマスクを作成しなければならない場合に、この作業を自動化できます:

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、すなわち1011
var mask2 = createMask(false, false, true); // 4、すなわち 0100
var mask3 = createMask(true); // 1、すなわち 0001
// etc.

alert(mask1); // 11 と表示、すなわち 1011

逆操作アルゴリズム: マスクから真偽値の配列を作成

マスクから BooleansArray を作成したい場合、以下のコードを用いることができます:

function arrayFromMask (nMask) {
  // nMask は -2147483648 から 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(", ") + "]");
// "[true, true, false, true]" と表示、すなわち 11 および 1011

両方のアルゴリズムを同時に検証できます。

var nTest = 19; // マスク
var nResult = createMask.apply(this, arrayFromMask(nTest));

alert(nResult); // 19

(Number.toString(2) メソッドがありますので) 教育的な目的のみになりますが、BooleanArray ではなく Number の 2 進表記を含む String を作成するためにarrayFromMask アルゴリズムがどのように操作しているかを示します:

function createBinaryString (nMask) {
  // nMask は -2147483648 から 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);
// 00000000000000000000000000001011 と表示、すなわち 11

仕様

仕様書 策定状況 コメント
ECMAScript 1st Edition (ECMA-262) 標準 最初期の定義
ECMAScript 5.1 (ECMA-262) 標準 仕様書内のいくつかのセクションで定義: Bitwise NOT operator, Bitwise shift operators, Binary bitwise operators
ECMAScript 2015 (6th Edition, ECMA-262) 標準 仕様書内のいくつかのセクションで定義: Bitwise NOT operator, Bitwise shift operators, Binary bitwise operators
ECMAScript 2017 Draft (ECMA-262) ドラフト 仕様書内のいくつかのセクションで定義: Bitwise NOT operator, Bitwise shift operators, Binary bitwise operators

ブラウザ実装状況

機能 Chrome Firefox (Gecko) Internet Explorer Opera Safari
ビットごとの NOT (~) (有) (有) (有) (有) (有)
ビットごとの AND (&) (有) (有) (有) (有) (有)
ビットごとの OR (|) (有) (有) (有) (有) (有)
ビットごとの XOR (^) (有) (有) (有) (有) (有)
左シフト (<<) (有) (有) (有) (有) (有)
右シフト (>>) (有) (有) (有) (有) (有)
符号なし右シフト (>>>) (有) (有) (有) (有) (有)
機能 Android Chrome for Android Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile
ビットごとの NOT (~) (有) (有) (有) (有) (有) (有)
ビットごとの AND (&) (有) (有) (有) (有) (有) (有)
ビットごとの OR (|) (有) (有) (有) (有) (有) (有)
ビットごとの XOR (^) (有) (有) (有) (有) (有) (有)
左シフト (<<) (有) (有) (有) (有) (有) (有)
右シフト (>>) (有) (有) (有) (有) (有) (有)
符号なし右シフト (>>>) (有) (有) (有) (有) (有) (有)

関連情報

ドキュメントのタグと貢献者

 このページの貢献者: scheakur, yyss, fscholz, teoli, ethertank
 最終更新者: scheakur,