ビット演算子の復習。
通常数値リテラルとして扱う場合は、10進数や8進数、16進数などを使用する機会が多いが、ビット演算子は32ビットの集合として扱うため2進数の計算となる。
2進数の計算は1ビットで示すことができる情報処理の基礎となるが、あまりコーポレートサイトなど静的なコーディングで使用する機会はない。
今回はビット演算子の復習のために、無理やりビットマスクを使ってみる。
ビットマスクとは
ビットマスクとは、通常真偽値として使用されるbool型は2種類としか値がないが、これを「真 = 1」「偽 = 0」として1ビットで表現することで、2進数を用い一つの変数で複数の真偽値を表現することである。
ビットマスクを用いることで、視認性が下がるがオブジェクトアクセスなどのメモリリソースを抑えられ、高速処理することができため、ゲームプログラミングなどでよく用いられる。
数値リテラルについて
各進数の使い方についてまとめてみた。
ヘキサリテラル
// 16進数表記(0x)
console.log(0x00000112); // 274
オクタルリテラル
// 8進数表記(0o)
console.log(0o00000112); // 74
バイナリリテラル
// 2進数表記(0b)
console.log(0b00000110); // 6
ビット演算子の種類
- a & b:ビットごとのAND
オペランドの対応するビットがともに 1 である各ビットについて 1 を返す。 - a | b:ビットごとのOR
オペランドの対応するビットがどちらかまたはともに 1 である各ビットについて 1 を返す。 - a ^ b:ビットごとのXOR
オペランドの対応するビットがどちらか一方のみ 1 である各ビットについて 1 を返す。 - ~ a:NOT:ビットごとのNOT
オペランドの各ビットを反転する。 - a << b:左シフト
2 進表現のa
をb
(< 32) ビット分だけ左にシフトし、右から 0 を詰める。 - a >> b:符号を維持した右シフト
2 進表現のa
をb
(< 32) ビット分だけ右にシフトし、溢れたビットは破棄する。 - a >>> b:0 埋め右シフト
2 進表現のa
をb
(< 32) ビット分だけ右にシフトします。溢れたビットは破棄し、左から 0 を詰める。
// AND
console.log(0b0101 & 0b1010); // 0 = 0b0000
// OR
console.log(0b0101 | 0b1010); // 15 = 0b1111
// XOR
console.log(0b0101 ^ 0b1011); // 14 = 0b1110
// NOT
console.log(~ 0b1110); // -15
各自 Developer Tool で試してみて欲しい。
ビットマスクの使用例
最後にビットマスクの使い方を見てみる。
let flag = 0b0000;
// 各フラグ
const A = 0b0001; // 1桁目をフラグに設定
const B = 0b0010; // 2桁目をフラグに設定
const C = 0b0100; // 3桁目をフラグに設定
// フラグの追加
flag = flag | A; // 0b0001
// 下記のようにも記述できる
flag |= B; // 0b0011
// フラグの削除
flag = (flag | B) ^ B; // 0b0001
// フラグの判定
console.log( (flag & A) !== 0 ); // true:Aのフラグを立っていれば、0以外の数値を返す