ビットシフト備忘録

ビットシフト

>> 右へ

<< 左へ

ある数を 2 倍, 1/2 倍(小数切捨)するときに有用。

この仕組みを理解するため、例、右シフト 1 がどうして 1/2 倍になるかを考える。

21 を 2 進数表記すると 10101 である。

parseInt(10101,2) = 21

2 進数では、各位の値が 1 (有る) か 0 (無い) かで表される。

16 8 4 2 1
 1 0 1 0 1

全ての位の和が、 21 である。

(16 * 1) + (8 * 0) + (4 * 1) + (2 * 0) + (1 * 1) = 21

これを右シフト 1 する。

21 >> 1

16 8 4 2 1
   1 0 1 0 1

(16 * 0) + (8 * 1) + (4 * 0) + (2 * 1) + (1 * 0) = 10

21 / 2 = 10.5 だが、ビット演算では小数が切り捨てられる。

x>>1 = Math.floor(x/2)

2 進数では、位が上がるごとに、値は 1,2,4,8,16,32,64,128... と大きくなっていく。

概ね…

どの位の値も、直前の位の値の 2 倍になっている。

どの位の値も、直後の位の値の 1/2 倍になっている。

右シフト 1 することは、各位の値を 1/2 倍することと等しい。

16 8 4 2 1
 1 0 1 0 1
    ↓
 8 4 2 1 0
 1 0 1 0 1

16→8, 8→4, 4→2, 2→1, 1→0

各位の値をすべて 1/2 倍して、足しているから、全体を 1/2 倍していることになる。

a/2 + b/2 + c/2 = (a+b+c)/2

(16 * 1) + (8 * 0) + (4 * 1) + (2 * 0) + (1 * 1) = 21
( 8 * 1) + (4 * 0) + (2 * 1) + (1 * 0) + (0 * 1) = 10

1 を 1/2 倍すると 0.5 である。 ビット演算では、これを 0 とする。

もしも、ビット演算に、 0.5 の位があるとしたら…

16 8 4 2 1
 1 0 1 0 1
    ↓
 8 4 2 1 0.5
 1 0 1 0 1

正確な値を求めることができる。