ビット列を右にずらすが、論理右シフトと違って左端には符号ビット(元の最上位ビット)がコピーされる。負の数を 2^N で割るときに符号を保つための演算です。
算術右シフトは、ビット列を右に N ビットずらす演算で、左端には符号ビット(元のMSB)が増殖するのが特徴です。
動作:
・左端には元の符号ビットがコピーされる
・右端からあふれたビットは捨てられる
・符号を保ったまま 2^N で割るイメージ
例: -16 を右に 2 シフト
・元: 11110000 = -16(2の補数)
・右2シフト: 11111100 = -4
・左に符号ビット 1 が 2 個コピーされた → 負のまま保たれる
・確認: -16 ÷ 2² = -16 ÷ 4 = -4 ✓
算術右シフトの最大の特徴は、右にずらしたときに左端の空席に「元の符号ビット(最上位ビット)を複製して入れる」ことです。論理シフトが常に 0 を入れるのと対照的。この仕組みのおかげで、シフト後も符号が保たれます。
・元が正の数 (MSB = 0):左端に 0 が複製される → 結果も MSB = 0 で正のまま
・元が負の数 (MSB = 1):左端に 1 が複製される → 結果も MSB = 1 で負のまま
この「符号ビットを複製」する動作のことを、英語では sign extension(符号拡張)と呼びます。シフト 1 回で 1 ビットの符号拡張、N 回シフトすると N ビット分の符号拡張が行われます。
論理右シフトとの比較:
| 論理右シフト | 算術右シフト | |
|---|---|---|
| 左端に入る | 必ず 0 | 元の符号ビット |
| −16 を 2 右シフト | 0011 1100 = 60 | 1111 1100 = −4 |
| 100 を 2 右シフト | 0001 1001 = 25 | 0001 1001 = 25 |
正の数(MSB = 0)に対する論理右と算術右は結果が完全に同じ。違いが出るのは負の数の時だけです。
算術右シフトは「符号付き整数を 2 で割る」のと同じ意味になります(端数は下向きに切り捨て)。N ビット右シフトなら 2^N で割る。
例: −16 (1111 0000) を右に 2 シフト → 1111 1100 = −4。確認: −16 ÷ 4 = −4 ✓。論理シフトだと 0011 1100 = 60 になり、本来の意味が壊れます。
なぜ符号ビットを複製すると ÷2 になるのか? 2 の補数表現の負の数は「左端が 1 で、それを含めて全体で 1 つの値を表す」形をしています。右にずらすときに左端を「同じ 1」で埋めれば、「負の数の桁を 1 つ落とした絶対値半分の負の数」になる、という綺麗な対応関係が成り立つのです。
注意点として、負の奇数の除算は数学的な値より小さい方に丸められる傾向があります。例: −5 ÷ 2 は数学的には −2.5 だが、算術右シフトでは −3 になる(−5 = 1111 1011 → 右シフト1 → 1111 1101 = −3)。これは「下向き切り捨て(floor)」と呼ばれる挙動です。
面白い性質: −1 は 2 の補数で 1111 1111(全ビット 1)。これを何回算術右シフトしても、左端に 1 が補われて常に −1 のままです。