ビット演算 【bitwise operation】
概要
ビット演算(bitwise operation)とは、主にコンピュータ上で行われる演算の一つで、対象データをビット列(2進数の0と1の羅列)とみなして、ビットの移動やビット単位の論理演算などを行うもの。コンピュータはすべての情報を内部的にはビット列として表しており、CPU(MPU/マイクロプロセッサ)にはビット演算用の命令が豊富に用意されている。機械語(マシン語)のプログラムでは様々な処理に用いられる演算であり、高水準言語のプログラムに直接記述されていなくても実際の処理では内部的に多用されている。
ビット単位の論理演算
ビット演算は大きく分けて二種類あり、その一つはビット単位の論理演算である。NOT演算はビット列の論理否定で、各ビットの「0」を「1」に、「1」を「0」に反転させる。「NOT 0101」の結果は「1010」となる。
AND演算は二つのビット列の同じ位置同士のビットで論理積(両方1の場合のみ1となる)を求める演算で、「0011 AND 0101」の結果は「0001」となる。OR演算は同様にビットごとの論理和(いずれかが1の場合に1となる)を求める演算で、「0011 OR 0101」の結果は「0111」となる。XOR演算はビットごとの排他的論理和(片方のみが1の場合に1となる)を求める演算で、「0011 XOR 0101」の結果は「0110」となる。
ビットシフト
もう一つのビット演算はビットの位置を入れ替える操作であり、一方向に単純に移動するシフト演算と、ビット列の先頭と末尾を繋いで循環させるローテート演算(循環シフト/環状シフト/ビット回転)に分かれる。
シフト演算はビット列の各桁を右(下位ビット方向)または左(上位ビット方向)に指定した数だけずらす操作で、「0010」を右に1ビットシフトすると「0001」に、左に1ビットシフトすると「0100」となる。
全ビットを一律に移動する動作を「論理シフト」(logical shift)、右シフトの際に最上位ビットを動かさずに保存する動作を「算術シフト」(arithmetic shift)という。算術シフトは最上位ビットを符号ビットとする符号付き整数を処理するのに適している。
端に追いやられたビットは消滅するが、CPU内部ではキャリーフラグと呼ばれる記憶領域に捨てられたビットの値がセットされ、後続の命令で参照できるようになっていることが多い。反対側から新たに出現するビットは原則として「0」にセットされるが、算術右シフトでは符号ビットのコピーが補充される。
ローテート
ローテート演算は、ビット列の最上位ビットの左隣を最下位ビット、最下位の右隣を最上位とみなして円環状にシフトする操作で、右端に追いやられたビットは左端に、左端に追いやられたビットは右端に出現する。例えば、「1001」を右に1ビットローテートすると「1100」に、左に1ビットローテートすると「0011」となる。
最上位ビットと最下位ビットの間にキャリーフラグが挟まっているとみなし、左端あるいは右端からキャリーにセットされた内容が出現する特殊なローテート演算が用意されている場合もあり、「キャリー付きローテート」と呼ばれる。
ビット演算子
プログラミング言語にはビット演算用の演算子が用意されている場合がある。言語によって仕様は異なるが、C言語の演算子の体系を引き継いでいる言語(C++言語やJava、JavaScriptなど)では多くが共通している。
これらの言語では、NOT演算は「~x」、OR演算は「x|y」、AND演算は「x&y」、XOR演算は「x^y」、左シフトは「x<<y」(xが対象ビット列、yが移動量)、右シフトは「x>>y」のように表記する。ローテートのための演算子は用意されていない。