ビット演算子は、数値をビット単位で演算を行うものです。
ビット論理積(AND) &
ビット論理和(OR) |
ビット排他的論理和(XOR) ^
ビット否定(NOT) ~
左シフト <<
符号あり右シフト >>
符号なし右シフト >>>
ビット演算子は、論理演算を行う際に使います。
それぞれのビットによるビット演算の結果は以下の通りになります。
AND
OR
XOR
NOT
A 0 1
答え 1 0
実際にプログラムを組んでやってみましょう。Practice2-1.htmlに以下のプログラムを加えてみましょう。
document.write( “a and b = “ + (a & b) + "<br>") ;
document.write( “a or b = “ + (a | b) + "<br>") ;
document.write( “a xor b = “ + (a ^ b) + "<br>") ;
document.write( “not a = “ + (~a) + "<br>") ;
document.write( “a << 3 = “ + (a << 3) + "<br>") ;
document.write( “a >> 3 = “ + (a >> 3) + "<br>") ;
document.write( “-a >> 3 = “ + (-a >> 3) + "<br>") ;
document.write( “-a >>> 3 = “ + (-a >>> 3) + "<br>") ;
仮に、aに53, bに7を代入したとしますと、このような結果になります。
aは10進数で53なので、16進数で表現すると 0x35 となります。2進数(8ビット)で表現すると
00110101
となります。
bは10進数で7なので、16進数で表現すると0x07となります。2進数(8ビット)で表現すると
00000111
となります。
AND OR
a 00110101 a 00110101
b 00000111 b 00000111
答 00000101 答 00110111
(5) (55)
XOR NOT
a 00110101 a 00110101
b 00000111
答 00110010 答 11001010
(50) (-54)
左シフト(<<)は、右側に <<の後の数値分左にビットをずらし、一番右に0を埋めます。
今回 a << 3 という式を書きましたので、a=53を3ビット左ずらすことになります。
00110101 →
01101010 →
011010100→
00110101000 (524)という結果になります。
次に右シフト演算になります。まずは、通常の右シフトです。
a >> 3ですので、
00110101 →
00011010 →
00001101 →
00000110 (6)という結果になります。
次に普通に、aを右シフトするのではなく、-a(マイナスa)を右シフトしてみます。aは53なので、-a は-53になります。
2進数の書き方ですが、
0(00000000)から1を引くと-1ですが2進数の演算では、その上の桁の1を借りて計算して、00000000 – 00000001 = 11111111となります。
マイナスの数字は一番上のビットが必ず1になります。
なので、2進数でマイナスの数値を出すときは、プラスの数値を全部反転させて1を足すといいです。
2だと、00000010 → 11111101(反転)→ 11111110(1足す)
となると-53は2進数で表すと11001011になります。ということでシフト演算を見てみましょう。
00110101 → 11001010 → 11001011 一番右が-53です。
符号付き右シフト(>>)は左シフトの逆になります。
数値分右にビットをずらし、もともとの数が
正(プラスまたはゼロ)の場合は一番左に0を埋め、
負(マイナス)の場合は一番左に1を埋めます(マイナスを維持するため)。
今回は-53と、負の数ですので、右にビットをずらす際に一番左には1が入ります。
11001011 →
11100101 →
11110010 →
11111001という結果になります。
10進数で表そうとすると先程の処理と逆をすればいいので、1引いて反転させます。
11111001 → 11111000 →00000111 となります。00000111は10進だと7ですので、答えとして-7となります。
符号なし右シフトは、もともとの数値が正だろうが負だろうが右にシフトしたあと一番左側に0を埋めます。そうすると
11001011 →
01100101 →
00110010 →
00011001という形になります。符号なしなので、一番上のビットに0が入ります。
一番上のビットが0ですので、符号なしでビットシフトすると、負の数が正の数に変わる(というより符号なしなので-53ではなく203と計算前に認識される)ことになります。
実際に出た結果は以下のようになります。実際にこの数値になることを確認してください。
あれ、-a >>>3の数値がすごく大きいですね。
実はここで説明する際、数値を8ビット(1バイト)で表現していましたが、実際1バイトだと符号付きだと127までしか表現できないので、javascriptでは、変数は32ビット(4バイト)で表現します。
ですから、-53はjavascript上では11001011でなく、
11111111 11111111 11111111 11001011です。
そのため、右に3ビットシフトすると
00011111 11111111 11111111 11111001となり、とても大きな数字として表現されました。
説明と違ってすみません。