シフト演算
久々にシフト演算を用いた処理を実装する機会があり、忘れていたので勉強しなおした。
以下はその備忘。
シフト演算とは
2進数のビットデータについて、そのデータの桁を 左 または 右 にずらす操作のこと。
左シフトの場合は左にずらす=1桁増える、右シフトの場合は右にずらす=1桁減る。
シフト演算すると数値はどう変わるのか
結論から言えば、
- n進数を 左シフト すると n倍 の値になる
- n進数を 右シフト すると 1/n倍 の値になる
具体例で言うと、
2進数 1010
(10進数換算で 10)の値を
- 左シフトすると
10100
つまり 10進数換算で20
(2倍) - 右シフトすると
101
つまり 10進数で5
(1/2倍)
10進数 8080
の値を
- 左シフトすると
80800
(10倍) - 右シフトすると
808
(1/10倍)
ということで、 2進数の場合は 2倍 もしくは 1/2倍、10進数の場合は 10倍 もしくは 1/10倍 となっていることが分かる。
論理シフト と 算術シフト
多くの場合、シフト演算は固定長のビットデータに対して行うもの。 その固定調のデータが符号を考慮する必要があるか否かにより、以下の2種類のシフト演算のうち適切なものを用いる必要がある。
- 算術シフト:固定調の先頭1桁が符号であることを前提とするシフト演算
- 論理シフト:固定調の中に符号の情報は含まれていないことを前提とするシフト演算
算術シフト(arithmetic shift)
算術シフトは、先頭1桁は符号として固定値として考え、シフトしても先頭1桁は変化させないシフト方法である。
先頭1桁が 1
の場合は 正数(+)、先頭1桁が 0
の場合は 負数(-)となる。
以下は8ビットの固定調であることを前提に例に考える。
正数に対して算術シフトを行う例
10001000
は 符号あり10進数換算では +8
となる。
- これを左シフトする場合、
10010000
となり、10進数換算では+16
となる。 - これを右シフトする場合、
10000100
となり、10進数換算では+4
となる。
負数に対して算術シフトを行う例
00001000
は 符号あり10進数換算では -8
となる。
- これを左シフトする場合、
00010000
となり、 10進数換算では-16
となる。 - これを右シフトする場合、
00000100
となり、 10進数換算では-4
となる。
上記のように、左シフト・右シフトのいずれを行う場合でも先頭1桁が変動しないシフト演算が 算術シフト
ということになる。
論理シフト(logical shift)
論理シフトは、符号の有無を考慮せず、全ての桁を純粋な数値として扱うシフト方法。
8ビットの固定調の値が 00001000
である場合、 符号なし10進数換算すると 8
となる。
- これを左シフトする場合、
00010000
となり、10進数換算では16
となる。 - これを右シフトする場合、
00001000
となり、 10進数換算では4
となる。
オーバーフロー と アンダーフロー
(あとで書く)