ビットシフトというのは、
2進数で表した整数を右または左に移動するということです。
右ビットシフトなら、最上位ビットに0を補填して最下位ビットを消し、
左ビットシフトなら、最上位ビットを消して最下位ビットに0を補填します。
例えば2進数で0111(=7)を1つビットシフトすると、
左ビットシフト 右ビットシフト
0111 1110(=14) 0011(=3)
基本的には、左ビットシフトするというのは2をかける、
右ビットシフトするというのは2で割るということです。
JavaScriptではこの演算を次のように表します。
7 << 1
7 >> 1
上が1つ左ビットシフトする、
下が1つ右ビットシフトするということを表しています。
負の整数を左ビットシフトすると、
11111111111111111111111111111111(=-1) << 2
=> 11111111111111111111111111111100(=-4)
これも1つ左ビットシフトすると2倍したことになりますが、
右ビットシフトすると、
11111111111111111111111111111100(=-4) >> 2
=> 11111111111111111111111111111111(=-1)
これも1つ右ビットシフトすると2で割ったことになります。
ただし、最上位ビットには1が補填されます。
負のときも0が補填されるのは符号なしビットシフトといって、
>>>で表します。
11111111111111111111111111111100(=-4) >>> 2
=> 00111111111111111111111111111111(=1073741823)
以上が通常の使い方ですが、ここからが本題、
JavaScriptはイレギュラーな使い方が色々できるのでそれを見ていきましょう。
まず、右項が負数の場合を考えます。
1 << -2 = 1073741824(=0x40000000)
2 >> -31 = 1
すなわち負の場合は、11111でマスク(&をとる)します。
これは正の場合でも同じです。
1 << 33 = 2
小数をビットシフトする場合は整数に直してからビットシフトします。
1.1 << 1 = 2;
-1.1 << 2 = -2
大きな数の場合は、2
32で割った余りになります。
ただし、余りの範囲は、-2
31 〜 2
31-1です。
((1 << 30) * 4 + 1.1) << 0 = 1
((1 << 30) * 2) << 0 = -2147483648 (=-231)
他にも試すことがありますが、結果は用意に推察できると思います。