IT基礎

基本情報 科目B ビット反転の例題 ― シフトと論理積で「並びを逆にする」

8ビットの並びを逆にするプログラムの空欄を、オリジナルの例題で解説します。シフト(<<・>>)と論理積(∧)・論理和(∨)の役割を、1周ずつ動きを追えるツールで確かめられます。

目次
  1. 例題
  2. 考え方:トランプの山を1枚ずつ移す
  3. 1周ずつ動かしてみる
  4. ほかの選択肢がちがう理由
  5. 同じことを Python で
  6. ビット演算の問題で使えるコツ
  7. この記事の用語

基本情報技術者試験の科目Bでは、ビット演算のプログラムがよく出ます。記号が多くて身構えてしまいますが、やっていることは「1つずつ取り出して、1つずつ積む」だけ、ということがよくあります。この記事では、8ビットの並びを逆にするプログラムを、オリジナルの例題で解いてみます。

例題

関数 reverse は、8ビット型の引数 x のビットの並びを左右逆にした値を返す。たとえば reverse(00110101) の戻り値は 10101100 である。空欄に入る正しいものを選べ。

演算子 ∧ はビットごとの論理積、∨ はビットごとの論理和、<< は論理左シフト、>> は論理右シフトを表す。

擬似言語
○8ビット型: reverse(8ビット型: x)
  8ビット型: b ← x
  8ビット型: r ← 00000000
  整数型: i
  for (i を 1 から 8 まで 1 ずつ増やす)
    [    空欄    ]
  endfor
  return r
空欄に入れる2行
アr ← (r << 1) ∨ (b ∧ 00000001)
b ← b >> 1
イr ← (r >> 1) ∨ (b ∧ 00000001)
b ← b << 1
ウr ← (r << 1) ∨ (b ∧ 10000000)
b ← b >> 1
エr ← r ∨ (b ∧ 00000001)
b ← b >> 1
答えを見る

正解はアです。理由は下で順番に説明します。

考え方:トランプの山を1枚ずつ移す

机にトランプの山が2つあるところを想像してください。左の山 b のいちばん上(右端)から1枚取って、右の山 r に積む。これを8回くり返すと、最初に上にあったカードがいちばん下に行き、並びがちょうど逆になります。

プログラムでは、この「1枚取る」「積む」「次のカードを上に出す」を、3つの演算で書いています。

やりたいこと書き方意味
b の右端を1つ取り出すb ∧ 00000001右端以外を0で消す(マスク)。結果は 0 か 1
r に場所を空けて積む(r << 1) ∨ …r を左へ1つずらし、空いた右端に取り出した1ビットを入れる
b の次のビットを右端へ出すb ← b >> 1使い終わった右端を捨てる
ポイント:取り出すのは b の右端、積む先は r の右端。r を左へ押し出しながら積むので、先に入れたビットほど左(上の桁)へ移っていきます。

1周ずつ動かしてみる

8ビットを入れて「1周すすめる」を押すと、ループ1回ごとの b と r が表に増えていきます。色のついたビットが、その周で移ったビットです。

i取り出した bit
(b ∧ 00000001)
r(積んだあと)b(>> 1 のあと)

ほかの選択肢がちがう理由

どの選択肢も、例の 00110101 で1〜2周だけ試すと見分けられます。上のツールで、入力を変えて確かめてみてください。

同じことを Python で

擬似言語の ∧ は Python の &、∨ は | です。Python の整数は8ビットで止まらないので、& 0xFF で下8ビットだけ残しています。

Python
def reverse(x):
    b = x
    r = 0
    for _ in range(8):
        r = ((r << 1) | (b & 0b00000001)) & 0xFF  # r を左へ1つずらし、b の右端を入れる
        b = b >> 1                                # b の右端を捨てて、次のビットを右端へ
    return r

print(format(reverse(0b00110101), '08b'))  # 10101100

ビット演算の問題で使えるコツ

記号に慣れると、ビット演算は「小さな部品の組み合わせ」に見えてきます。最初はゆっくりで大丈夫です。

この記事の用語

言葉を選ぶと「☆ 単語を保存」が出ます。ここで保存した言葉は、単語帳の「用語」に入ります。

基本情報まとめで復習する →

← 記事一覧へ戻る