見出し画像

高校向けPython入門(7)実習課題例:2進法と16進法

 情報の授業での実習課題例である。プログラミングの節に限らず,モデル化とシミュレー ション,データの分析などでも Python を使ってできる実習例を掲載する。実行結果のスクリーンショットがないものについては,ソースコードをコピーして実行して確かめられたい。

7.1 情報のディジタル化

 文字コードや RGB カラーなどの情報のディジタル化の節では,教科書を読んで終わりとなりがちだが,実際にコンピュータを使って実習するほうが理解につながる。ここではプログラミングが目的ではないので,基本的なコードだけでできるようにしたい。アルゴリズムも簡単なほうがいい。そうでない場合はできたコードをツールとして渡して,少しだけ変えれば動くようにすればよい。その際,Python での書法や変数の概念などをどの程度教えるかが問題になるが,キータイピングの速度などの生徒のスキルも考慮して工夫する必要があるだろう。あとのことを考えれば,2コマほどをかけて基本的な変数の概念と制御構造だけでも教えておくのがよいのではないだろうか。

7.1.1 2 進法と 16 進法

 10 進法であらわされた正の整数 n を 2 進法で表す。
与えられた数を 2 で割っていき,余りを右から並べていくという方法だ。結果は文字列にするので,+ 演算子で結合していく。ここで,商を整数で求める割り算の演算子 // を使う。 次のコードでは n を入力するようにしているが,入力のチェックはしていないので,正の整数以外を入力すると正しく動かない。したがって,input で入力するのではなく,変換したい数を n に代入するようにしてもよいだろう。 

n = int(input("変換する数を入力 "))
b = ''          # シングルクォーテーション2つで空文字に 
while n > 0:
    bit = n % 2
    b = str(bit) + b
    n = n // 2
print(b)

 空文字を表すには,ダブルクォーテーションだと "" でわかりにくいかもしれないので,シ ングルクォーテーションにしたが,いずれにしても実習時には説明が必要だろう。
 組み込み関数の bin(n) で基数変換ができるので,print(bin(n)) で結果を確かめてもよい。それならばわざわざやるまでもない,と思われるかもしれないが,そうではなく,アルゴリズムをコード化することで,基数変換の方法を理解するのが目的なのだ。
 while の繰り返し条件を n > 0 ,つまり「商が正の間」としている。手計算のときは,最後の 1 も 2 で割って,商 0,余り 1 まで進めることもあるだろう。では,while n >= 0 と するとどうなるか。予想させて実行し,その結果について考えさせるのもよいだろう。コード量は少ないが,2 進法への変換のアルゴリズムと,そのコーディングについて考えさせるのにちょうどよい課題である。

 次に,小数の変換。無限小数への対処は,while ループにして,途中から break で抜ける 方法も考えられるが,ここでは,16 位までの条件で while を終わるようにした。

n = 0.8125b = '0.'
while len(b) < 18 and n > 0:
    bit = int(n * 2)
    n = n*2 - bit
    b = b + str(bit)
print(b)

 実習では,正の整数の場合と小数の場合では,b と str(bit) の結合の順序が違うことを 確認しておきたい。n = 0.8125 のところは input() にしてもよい。

 負の整数の変換では,絶対値を 2 進法で表してからビット反転し,1を加える,という手順にする。任意の数でもよいが,符号ビットの関係もあるので,-128 までの数で,8 ビット表示 と限定する。アルゴリズムはいろいろ考えられるが,ここではリストを使ってやってみよう。

n = int(input('負の数を -128 までの範囲で入力 '))
n = abs(n)        # n の絶対値
b = [1,1,1,1,1,1,1,1] 
m=0
while n > 0:
    bit = n % 2 
    b[7-m] = 1 - bit    # ビット反転して代入
    n = n // 2 
    m = m + 1
carry = 1   # 1を加えた繰り上がり。はじめは1
for i in range(8):
    bit = b[7-i]
    b[7-i] = (bit + carry) % 2
    carry = (bit + carry) // 2    # 繰り上がり
print(b)

適当なところに print 文を入れて,途中経過を表示してみるのもよい。
ビット反転とそれをどう実現するかは初心者には難しいだろうから,実際の授業ではパスするところかもしれない。コード量が増えるので,全部打ち込むとかなり時間がかかる。そこは,生徒の状況に応じて適宜。

 2 進法から 10 進法への変換では,小数や正の整数はよいが,負の数はビット数を決めない のはあまり現実的ではないので(通常,整数は 8 ビットの倍数を使って表す)ここでは,正 の整数とする。小数については読者への課題とするが,授業で扱うことはないと思われる。

s = input("2進数を入力。8桁まで。 ")
n = len(s)
d = 0
for i in range(n):
    bit = s[n-i-1]
    d = d + int(bit) * 2**i
print(d)

 10 進法から 16 進法への変換は,2 進数と原理は同じだが,正の整数だけをやっておけば よいだろう。ただし,10 以上の数が A~F で表されるので,計算だけでは変換できない。0 ~Fの文字のリストを作っておいて,そこから取りだすようにする。

n = int(input('10進数を入力 '))
keta = ["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"] 
h = ''
while n > 0:
    a = n % 16
    h = keta[a] + h
    n = n // 16
print(h)