FE EXAM

シフト演算

ビットを左右にずらす操作。左シフトは×2、右シフトは÷2と同じ効果があり、高速な掛け算・割り算に使われます。

SHIFT OPERATION
シフト前
シフト後
埋めビット
シフト前
5
シフト後
10
符号付き
10
演算
論理左 1bit ×2¹
5
0255
ビット数
シフト種類
方向
シフト量1
17
プリセット
解説

📌
シフト演算とは

ビット列を左右にスライドさせる操作00001010=10↓ 左シフト 1ビット00010100=20

シフト演算は、ビット列全体を左または右にスライドさせる操作です。たとえば8ビットの「00001010」(10進で10)を左に1ビットシフトすると「00010100」(10進で20)になります。値がちょうど2倍になっていますね。

左に1ビットシフトすると値が2に、右に1ビットシフトすると値が半分になるという、乗除算と密接な関係があります。これはシフト演算の最も重要な性質で、基本情報技術者試験でも頻出します。

シフト演算には論理シフト、算術シフト、循環シフトの3種類があります。それぞれ「空いた桁に何を埋めるか」が異なります。上のツールでスライダーを動かすと、ビットがどう移動し値がどう変わるかリアルタイムで確認できます。

📌
論理シフト

空いた桁は常に0で埋める左シフト ←←右側を0で埋める右シフト →→左側を0で埋める

論理シフトは最もシンプルなシフト演算です。ルールはたった1つ:
・ビットを指定方向にスライドし、空いた場所は常に0で埋める

具体例を見てみましょう。8ビットの「11001010」(10進で202)を論理右シフト1ビットすると:
・ビット全体が右に1つずれる
・右端の「0」がはみ出して消える
・左端に0が埋められる
・結果:01100101(10進で101)
202 → 101 で、ちょうど半分になっています。

論理シフトは符号なし整数(unsigned)に使います。符号ビット(先頭ビット)を特別扱いしないため、負の数(先頭が1)に論理右シフトを適用すると、先頭が0に変わって正の数になってしまいます。負の数を正しくシフトしたい場合は、次のカードで説明する「算術シフト」を使います。

論理シフトが使われる場面
画像処理のRGB分解:0xRRGGBB から緑(G)を取り出すとき、右に8ビット論理シフトしてからマスクする
マスク生成1 << 3 で「ビット3だけが1」のマスク 00001000 を作る
符号なし整数の高速÷2:配列のインデックス計算など、常に正の値を扱う場面で

上のツールで「論理」を選んで試してみてください。

📌
算術シフト

右シフト時に符号ビットを保持するシフト前: 11000000 (-64)11000000↓ 算術右シフト 2ビットシフト後: 11110000 (-16)11110000

論理シフトには1つ問題があります。負の数を右シフトすると、符号が変わってしまうのです。例えば -64(11000000)を論理右シフトすると、左側が0で埋められて 00110000(+48)になり、マイナスがプラスに化けます。

算術シフトはこの問題を解決します。右シフト時に空いた左側を0ではなく、元の符号ビット(MSB)と同じ値で埋めるのがポイントです。
・負の数(MSB = 1)→ 空いた場所を1で埋める
・正の数(MSB = 0)→ 空いた場所を0で埋める(論理シフトと同じ結果)

具体例を見てみましょう。8ビットの -64 を算術右シフト2ビットすると:
・シフト前:11000000(-64、MSB = 1)
・右に2ビットずらす:ビット全体が右に移動、右端の2ビットははみ出して消える
・空いた左側2ビットをMSBの1で埋める11110000(-16)

なぜ2ビットずらすと÷4になるのか?右シフト1ビットは÷2です。2ビットは÷2を2回繰り返すので÷4になります。
・右シフト1ビット = ÷2
・右シフト2ビット = ÷2 × ÷2 = ÷4
・右シフト3ビット = ÷8
・右シフト4ビット = ÷16 ...
一般に、右シフトnビット = ÷2n です。
検算:-64 ÷ 4 = -16 ✓ 負の数のまま正しく割り算できています。論理シフトだと -64 が正の数に化けてしまいますが、算術シフトなら符号が保たれたまま正確に除算できます。

なお、算術左シフトは論理シフトと同じ動作(右側を0で埋める)です。

算術シフトが使われる場面
符号付き整数の高速÷2:C言語やJavaの int x = -100; x >>= 1; は算術右シフトで -50 になる
平均値の計算(a + b) >> 1 で高速に2つの値の平均を求める(負の値でも正しく動作)
信号処理のスケーリング:音声データの音量を半分にするとき、各サンプル値を算術右シフトで÷2する

特に重要なのは「算術右シフトで符号が保存される」という点です。上のツールで「算術」を選び、負の値を右シフトして確認してみてください。

📌
左シフト=×2、右シフト=÷2 の関係

操作例 (10)結果等価な計算
左シフト110≡0000101020≡00010100×2¹ = ×2
左シフト210≡0000101040≡00101000×2² = ×4
左シフト310≡0000101080≡01010000×2³ = ×8
右シフト110≡000010105≡00000101÷2¹ = ÷2
右シフト210≡000010102≡00000010÷2² = ÷4

左シフトnビットは×2ⁿ、右シフトnビットは÷2ⁿに相当します。なぜでしょうか?10進数で考えてみてください。「15」の各桁を左に1つずらすと「150」になりますが、これは×10です。同様に2進数では各桁を左に1つずらすと×2になるのです。

この性質は乗除算よりも高速に実行できるため、プログラミングの最適化にも使われます。たとえば「×10」は「×8 + ×2」つまり「左3シフト + 左1シフト」で実現できます。上のツールでシフト量を変えて、値がどう変化するか試してみてください。

📌
循環シフト(ローテート)

はみ出たビットが反対側に回る10101011 01010111左端の1が右端に回り込む(情報が失われない)

循環シフト(ローテート)は、論理シフトや算術シフトとは根本的に違います。はみ出したビットを捨てるのではなく、反対側に回り込ませます。ベルトコンベアのように、端まで行ったビットがぐるっと戻ってくるイメージです。

具体例を見てみましょう。8ビットの「10101011」を左循環シフト1ビットすると:
・ビット全体が左に1つずれる
・左端の「1」がはみ出す
・はみ出した「1」が右端に回り込む
・結果:01010111
ビットが1つも失われていないのがポイントです。8ビットを8回循環シフトすると、元の値に完全に戻ります。

循環シフトが使われる場面
暗号化アルゴリズム(AES、DES、SHA-256):ビットを混ぜ合わせてデータの解読を困難にする
チェックサム計算:データの整合性検証で、ビットパターンを回転させながら計算
ビットフィールドの操作:特定のビット範囲を別の位置に移動する

上のツールで「循環」を選ぶと、埋めビット(黄色)がはみ出したビットと同じ値になることを確認できます。

📌
シフト演算の実用例

「ビットをずらすだけで何の役に立つの?」と思うかもしれませんが、シフト演算はプログラミングの様々な場面で使われています。

実用例1: 高速な掛け算・割り算
x * 10(x<<3)+(x<<1)掛け算命令(遅い)シフト+加算(速い)

CPUにとって、シフト命令は掛け算命令より何倍も速いです。例えば x = 3 を10倍したいとき:
左シフト3ビット = ×8 なので、3 << 3 = 3 × 8 = 24
左シフト1ビット = ×2 なので、3 << 1 = 3 × 2 = 6
・24 + 6 = 30(= 3 × 10 ✓)
つまり「×10」という1回の掛け算を、「×8 と ×2 のシフト2回 + 足し算1回」に分解できます。コンパイラがこの最適化を自動で行うこともあります。

実用例2: マスク生成(特定ビットの操作)
1 << 3 =00001000ビット3だけが1のマスクができる

1 << 3 で 00001000 が作れます。AND/ORと組み合わせて、特定ビットの検査・セット・クリアを行います。ハードウェア制御やフラグ管理に必須です。

実用例3: 色の分解(RGB値の取り出し)
0xRRGGBB (24bit color)RRGGBB>> 8& 0xFFG緑(G)だけを取り出せる

画像の1ピクセルは 0xRRGGBB の24ビット。緑(G)を取り出すには (pixel >> 8) & 0xFF でシフト+マスクします。

📌
多ビットシフト — nビットシフト = ×2ⁿ

シフト量左シフトの効果右シフトの効果例 (value=3)
1×2÷23→6, 3→1
2×4÷43→12, 3→0
3×8÷83→24, 3→0
4×16÷163→48, 3→0

nビットのシフトは、1ビットシフトをn回繰り返すのと同じです。左シフトnビットは×2ⁿ、右シフトnビットは÷2ⁿです。たとえば値3を左シフト4ビットすると 3×2⁴ = 3×16 = 48 になります。

右シフトでは小数点以下が切り捨てられる点に注意してください。値3を右シフト2ビットすると 3÷4 = 0.75 ですが、整数のシフトでは結果は0になります。上のツールのシフト量スライダーを動かして、値がどう変化するか試してみてください。

📌
符号ビット(MSB)とは

8ビット整数の「先頭ビット」が正か負かを決める正の数00010110= +22負の数11101010= -22

コンピュータが整数を表すとき、ビット列の一番左のビット(=MSB、最上位ビット)が「正か負か」を表す符号ビットになります。
・MSB が 0:正の数
・MSB が 1:負の数

なぜ算術右シフトで符号が保たれるのか。右シフトすると左端に空きが生まれます。論理シフトはその空きを必ず 0 で埋めるため、負の数(MSB=1)を右シフトすると MSB が 0 に変わり、マイナスがプラスに化けてしまいます。算術シフトは空きを元の MSB(符号ビット)と同じ値で埋めるので、正なら 0 埋め・負なら 1 埋めとなり、符号が変わりません。

身近な例で考えると、「マイナスのラベルが貼ってある箱」を右に1段ずらしたとき、左端にできた空き棚にも同じ「マイナスのラベル」を引き継いで貼る——それが算術シフトです。引き継がずに「プラス(0)のラベル」を貼るのが論理シフトです。

📌
3種類のシフトをひと目で比べる

右シフト1ビット時の「空いた左端」の扱い論理シフト0← 常に 0 を詰める算術シフトS← 符号ビット(S)と同じ値を詰める循環シフトR← はみ出た右端ビット(R)が戻る
種類空き埋め符号保存主な用途
論理シフト0 固定保証なし符号なし整数の ×÷2
算術シフト符号ビットと同じ保たれる符号付き整数の ×÷2
循環シフトはみ出たビット変わりうる暗号・ハッシュ計算

3つのシフトの違いは「右シフトのときに左端の空きを何で埋めるか」だけです。左シフトはどの種類でも右端を 0 で埋めます(循環シフトを除く)。
論理シフト:符号に関係なく 0 を詰める。符号なし整数(0以上の整数のみ)に向く
算術シフト:元の符号ビットを引き継ぐ。負の数を右シフトしても符号が保たれる。符号付き整数に向く
循環シフト:はみ出したビットが反対側から戻ってくる。情報が一切失われない

練習問題

🎯
基本情報技術者 練習問題

Q1.8ビットの値「00001010」(10進数で10)を論理左シフト2ビットした結果はどれか。
A.00101000(40)
B.00010100(20)
C.00000010(2)
D.10100000(160)
Q2.8ビットの値「11000000」を算術右シフト2ビットした結果はどれか。
A.00110000
B.11110000
C.11000000
D.00000011

関連コンテンツ