シフト演算で掛け算・割り算をする
左シフトを組み合わせて x を3倍・5倍・10倍にする手順と、論理右シフト・算術右シフト(負数を含む)を手で計算できるようになる。上位と下位のビットを入れ替えた値を、÷ と % を使った式で表せるようになる。
2進数ではビットを1桁ずらすだけで2倍や1/2になるので、CPU は掛け算・割り算をシフトと足し算に置き換えて速く計算します。科目Aでは「x を何倍にする操作はどれか」「算術右シフトした結果はいくつか」という形で、繰り返し出題されています。
このレッスンで稽古する(用語チェック・過去問)結論:左に1ビットずらすと2倍、右に1ビットずらすと1/2
シフト演算とは、ビット列(0と1の並び)を丸ごと左か右へずらす操作です。左に n ビットずらすと 2^n 倍、右に n ビットずらすと 2^n で割った値(割り切れない分は切り捨て)になります。
たとえば 10進数の 37 の右に 0 を付けて 370 にすると10倍になります。2進数で同じことをすると、1桁あたり2倍になります。
| 操作 | 値の変化 | 例(x=3 = 0011) |
|---|---|---|
| 1ビット左シフト | 2倍 | 0110 = 6 |
| 2ビット左シフト | 4倍 | 1100 = 12 |
| 3ビット左シフト | 8倍 | 11000 = 24 |
| 1ビット右シフト | 1/2(切り捨て) | 0001 = 1 |
左へずらしてレジスタ(CPU 内の小さな記憶場所)の幅からはみ出すことを**桁あふれ(オーバフロー)**といいます。過去問の多くは「桁あふれは起こらないものとする」と断っているので、計算では気にしなくて大丈夫です。
最頻出:シフトと足し算で ○倍 を作る
シフトだけで作れるのは 2倍・4倍・8倍…だけです。3倍・5倍・10倍は、シフトした値に元の x を足して作ります。この知識は本試験系と免除試験を合わせて16回出ていて、このレッスンで一番大事です。
解き方は、選択肢の操作を順に x の式へ書き直すだけです。「2ビット左シフト」は 4x、「x を加算」は +x、「さらに1ビット左シフト」は ×2 と置き換えます。
| 作りたい倍数 | 分解 | 操作 |
|---|---|---|
| 3倍 | 2x + x | 1ビット左シフト + x |
| 5倍 | 4x + x | 2ビット左シフト + x |
| 9倍 | 8x + x | 3ビット左シフト + x |
| 10倍 | (4x + x) × 2 | 2ビット左シフト + x、さらに1ビット左シフト |
| 12倍 | 8x + 4x | 3ビット左シフト + 2ビット左シフト |
ビット列で書かれた問題では、**末尾に 0 を1個付けると1ビット左シフト(2倍)**と同じ意味になります。b₁b₂…bₙ0 は 2倍、b₁b₂…bₙ00 は 4倍です。
右シフトには「論理」と「算術」の2種類がある
右へずらすと左端(上位)に空きができます。空いた所を何で埋めるかで2種類に分かれ、この違いが試験でよく問われます。
| 論理シフト | 算術シフト | |
|---|---|---|
| 扱う数 | 符号を考えないビット列(符号なし) | 2の補数で表した符号付きの数 |
| 右シフトで空いた上位を埋める値 | 常に 0 | 符号ビットと同じ値(負なら1、正なら0) |
| 符号ビット | ほかのビットと同じようにずれる | 残る(正負が変わらない) |
| 負数を右シフトした結果 | 大きな正の数になって意味が崩れる | 1/2^n 倍の負数になる |
たとえるなら、算術シフトは「先頭の旗(符号)を立てたまま列全体を後ろへ詰める」操作です。論理シフトは旗のことを考えず、空いた所に 0 を入れます。
論理右シフトは16進を2進に開いてから
16進数1桁は2進数4桁にそのまま対応します。16進 → 2進に展開 → ずらす → 4桁ずつ区切って16進に戻す、の順で計算します。
16進の桁をそのまま横にずらして「AF34」のようにするのは誤りです。1ビットずらすだけで、4桁区切りの中身がすべて変わります。
算術右シフトで負数を割る
前のレッスンの2の補数(ビットを反転して1を足し、負数を表す方法)が、ここで役に立ちます。負数を算術右シフトすると、空いた上位に 1 が入るので、負のまま 1/2^n になります。
注意点は端数の扱いです。算術右シフトの端数は小さい方へ切り捨てられます。−20 ÷ 8 = −2.5 は −2 ではなく −3 になります。
上位と下位を入れ替える式(免除試験で出題)
16ビットの x では、上位8ビットは x÷256(商)、下位8ビットは x%256(余り)です。2^8 = 256 だからです。入れ替えると、下位にあった値が上位(×256)へ、上位にあった値が下位へ移るので、(x%256)×256 + (x÷256) になります。
2桁の2進数 x₁x₂ でも考え方は同じです。x = 2x₁ + x₂、x₁ = int(x/2) なので、入れ替えた値は 2x₂ + x₁ = 2x − 3·int(x/2) になります。迷ったら x = 1 や x = 2 を代入して確かめるのが確実です。
x を10倍にするシフト操作を選ぶ
ア x を 2 ビット左にシフトした値に x を加算し,更に 1 ビット左にシフトする。
イ x を 2 ビット左にシフトした値に x を加算し,更に 2 ビット左にシフトする。
ウ x を 3 ビット左にシフトした値と,x を 2 ビット左にシフトした値を加算する。
エ x を 3 ビット左にシフトした値に x を加算し,更に 1 ビット左にシフトする。
解き方と答えを見る
- 10x を「シフト(2のべき乗倍)と足し算」に分解する。10x = (4x + x) × 2
- 4x は2ビット左シフト、+x は加算、×2 は1ビット左シフトにあたる
- 選択肢を式に直して確かめる。ア:(4x + x) × 2 = 5x × 2 = 10x
- イ:(4x + x) × 4 = 20x。ウ:8x + 4x = 12x。エ:(8x + x) × 2 = 18x
- 10x になるのはアだけ
答え:ア(2ビット左シフトして x を加え、さらに1ビット左シフトする)
2ビット左シフトして x を加えると何倍になるか
ア 3
イ 4
ウ 5
エ 6
解き方と答えを見る
- 2ビット左シフト = 2² 倍 = 4x
- x を加える:4x + x = 5x
答え:ウ(5倍)
16進 ABCD を2ビット論理右シフトする
ア 2AF3
イ 6AF3
ウ AF34
エ EAF3
解き方と答えを見る
- 16進を2進に展開する:A=1010, B=1011, C=1100, D=1101 → 1010 1011 1100 1101
- 右に2ビットずらす。右端の2ビット「01」は消える
- 論理シフトなので、空いた上位2ビットを 0 で埋める → 0010 1010 1111 0011
- 4桁ずつ16進に戻す:0010=2, 1010=A, 1111=F, 0011=3 → 2AF3
- 32ビットのレジスタでも、ABCD より上位はすべて 0 なので結果は変わらない
答え:ア(2AF3)
11010000 を2ビット算術右シフトし、00010100 から引く
ア 00001000
イ 00011111
ウ 00100000
エ 11100000
解き方と答えを見る
- 11010000 は最上位が1なので負の数。10進に直すと 208 − 256 = −48
- 2ビット算術右シフト:空いた上位2ビットを符号ビットの1で埋める → 11110100
- 11110100 = 244 − 256 = −12(−48 ÷ 4 = −12 と一致)
- 00010100 = 16 + 4 = 20
- 20 − (−12) = 32
- 32 を8ビットの2進にすると 00100000
答え:ウ(00100000)
−20 を3ビット算術右シフトする
ア −115
イ −3
ウ −2
エ 27
出典:基本情報技術者試験 科目A免除 修了試験 20110724 実施分 問2
解き方と答えを見る
- 20 を8ビットにする:00010100
- 2の補数を作る:ビットを反転して 11101011、1を足して 11101100(= −20)
- 3ビット算術右シフト:右端の3ビット「100」が消え、上位3ビットを符号ビットの1で埋める → 11111101
- 11111101 = 253 − 256 = −3
- 確認:−20 ÷ 8 = −2.5 を小さい方へ切り捨てると −3
答え:イ(−3)
16ビットの上位8ビットと下位8ビットを入れ替える式
ア (x÷256)+(x%256)
イ (x÷256)+(x%256)×256
ウ (x÷256)×256+(x%256)
エ (x÷256)×256+(x%256)×256
出典:基本情報技術者試験 科目A免除 修了試験 20220123 実施分 問1
解き方と答えを見る
- 上位8ビットの値 = x ÷ 256、下位8ビットの値 = x % 256
- 入れ替え後は、元の下位が上位に来るので (x % 256) × 256
- 元の上位は下位に来るので、そのまま x ÷ 256
- 合計:(x ÷ 256) + (x % 256) × 256
- ウ (x÷256)×256 + (x%256) は元の x そのもので、入れ替わっていない
答え:イ
要点(試験直前に読む)
- 左に n ビットずらすと 2^n 倍、右に n ビットずらすと 1/2^n(端数は切り捨て)
- 3倍 = 2x + x、5倍 = 4x + x、10倍 = (4x + x) × 2。選択肢は x の式に直して確かめる
- 末尾に0を付けると2倍。b…b0 + b…b は3倍
- 右シフトで空いた上位は、論理シフトなら0、算術シフトなら符号ビットで埋める
- 負数の算術右シフトは小さい方へ切り捨てる。−20 を3ビットずらすと −3(−2 ではない)
- 16ビットの上位8ビット = x÷256、下位8ビット = x%256。入れ替えると (x%256)×256 + x÷256
ひっかけ
- シフト量を少し変えて 12倍・18倍・20倍 になる選択肢を並べる → 選択肢を1つずつ 4x・8x などの式に直して計算する
- 「2ビット左シフトして x を加える」で、加算前の4倍を選ばせる → 最後の加算まで式に入れる(答えは5倍)
- 算術シフトの問題で、上位を0で埋めた答え(大きな正の数)や、符号ビットだけ残して空きを0で埋めた答え(−115 など)を混ぜる → 負数の算術右シフトなら、上位はすべて1で埋まる
- 16進の桁をずらしただけの答え(ABCD → AF34 など)を混ぜる → 必ず2進に展開してからずらす
- 上下入れ替えの式で、元の値に戻る式や重みの付け方が逆の式を混ぜる → x = 1 などを代入して入れ替わっているか確かめる
用語(12)
ビット列全体を左または右へ指定した桁数だけずらす操作。
⚠ ローテート(循環シフト)は、はみ出したビットを反対側へ戻す。シフトでは、はみ出したビットは捨てる。
ビット列を上位方向へずらし、空いた下位を0で埋める操作で、nビットなら値は2^n倍になる。
⚠ 右シフトは1/2^n。「左=増える、右=減る」と覚える。
ビット列を下位方向へずらす操作で、nビットなら値は2^nで割った値(端数切り捨て)になる。
⚠ 空いた上位を0で埋めるか符号ビットで埋めるかで、論理と算術に分かれる。
符号を考えずにずらし、空いたビットを常に0で埋めるシフト。
⚠ 算術シフトとの違いは、右シフトで上位を0で埋めるか符号ビットで埋めるか。負数の問題なら算術シフトを疑う。
2の補数の符号付き数を、符号を保ったままずらすシフトで、右シフトでは空いた上位を符号ビットと同じ値で埋める。
⚠ 論理シフト(常に0で埋める)。問題文の「算術」「論理」の2文字を必ず確認する。
2の補数表現の最上位ビットで、0なら正(または0)、1なら負を表す。
⚠ 論理シフトでは、ほかのビットと同じようにずれて上書きされる。
ビットを反転して1を足すことで負数を表す方法で、8ビットなら −128〜127 を表せる。
⚠ 1の補数は反転するだけで1を足さない。
計算結果がレジスタのビット数に収まらず、正しい値を保てなくなること。
⚠ 右シフトで下位から消えるビットは端数の切り捨てで、オーバフローとは呼ばない。
CPU の中で計算中の値を一時的に置く、高速で小さな記憶場所。
⚠ 主記憶(メモリ)より容量は小さいが、ずっと速い。
ビット列の左側(重みが大きい側)を上位、右側(重みが小さい側)を下位という。
x を 2^n で割った商は上位側のビットを、余りは下位 n ビットを表す。
⚠ 16ビットを8ビットずつに分けるときは 256 で割る(2^16 = 65536 と混同しない)。
0〜9とA〜F(10〜15)で表す数で、1桁が2進4桁にちょうど対応する。
⚠ 16進の桁をそのままずらしても、ビットシフトにはならない。
このレッスンの過去問
- 左シフトによる2のべき乗倍と加算平成29年度 秋期 基本情報技術者試験 午前 問1
- 論理右シフトの計算平成25年度 秋期 基本情報技術者試験 午前 問2
- 2の補数表現数の算術右シフト平成24年度 秋期 基本情報技術者試験 午前 問1
- 2進2桁の上下ビット入替え式基本情報技術者試験 科目A免除 修了試験 20220123 実施分 問1