Python でM進数をN進数に変換する
《プログラム1》 「10進数を2進数に変換する」には〈手順1〉のように「2で割り続けて、余りを逆順に表示」すればよい。
《プログラム2》 「5進数を10進数に変換する」には〈手順2〉のように「各位の値×5ⁿ」を足し合わせればよい。
これらのやり方は、高校数学Aの「整数の性質」でも出てきます。
さて、実際にコードを組もうとすると、《プログラム1》で手こずるのは「余りを『逆順に』表示する」ところでしょうか。でもその部分は《プログラム2》の〈手順2〉の考え方が使えます。2つ以上の数を並べて表示するということは「10進数のように見せかける」とも言えるわけでありまして、〈手順2〉で「5ⁿ の値を足した」部分、その部分を「10ⁿ の値を足す」ように変えれば良いわけです。上の〈手順2’〉がそれです。
《プログラム2》で厄介なのは「4桁の数 1234 を『1 と 2 と 3 と 4 に分解』する」ところでしょうか。「1桁ずつ分けて入力する」方法もありますが、その部分は《プログラム1》の〈手順1〉の考え方が使えます。〈手順1〉では「2で割り続けた」わけですが、「10 で割り続け」れば、結果として各位の数に分かれますね。上の〈手順1’〉がそれです。
そう考えると、《プログラム1》と《プログラム2》は同じような書き方で出来そうです。では、実際にプログラムを、単純なものから始めて、汎用性のあるものまで作ってみましょう。
最後は意外とスッキリ書けるかもしれませんよ。
10進数を2進数に変換する
「10進数を2進数に変換する」には「10進数を2で割り続けて、その都度の余りを逆順に表示」すればよい。終わるタイミングは「商が0」になったとき(言い換えると「商が正」の間は割り続ける)。たとえば下のようにやることで「 19₍₁₀₎=10011₍₂₎ 」となります。
さて、このプログラムを組む際に手こずるのは「余りを『逆順に』表示する」ところでしょうか。それについて、先ほど大きなヒントを言っちゃったのですが、いったん忘れてください。
そうなると、最初に出てきた余りを最後に表示するわけですから、余りの値を保存する変数が必要になります。そしてその個数は分からないわけですから、配列変数が良いでしょう。その名もズバリ amari という配列変数を設定することにします。
5行目から8行目までが「2で割り続ける」部分で、2で割りながら、その都度、余りを配列 amari に1つずつ入れています。
9行目と10行目が「2進数を表示する」部分で、配列 amari の数を1つずつ「逆順に」表示しています。
n=int(input("10進数を入力してください "))
i=0
amari=[]
print(n,end="(10)=")
while n>0: # ┐ ← 商が0になるまで、2で割り続ける
amari.append(n%2) # │ ← 配列変数を追加しながら余りを格納する
i=i+1 # │
n=n//2 # ┘
for j in range(i): # ┐
print(amari[i-j-1],end="") # ┘ ← 余りを逆順に表示する
print("(2)")
5進数を10進数に変換する
次に「5進数を10進数に変換」してみましょう。手作業の手順は次の通りです。
ところで「1234」という数を見たとき、人は「1 と 2 と 3 と 4」の4つの数字をまず見るでしょうけれど、コンピュータはこれを1つの数としてしか認識しませんから、コンピュータに上の計算をさせるためには「各位の数をバラバラに分けて」与えなければなりません。
このプログラムを組む際に厄介なのは、その点でしょうか。それについても、先ほど大きなヒントを言っちゃったのですが、いったん忘れてください。
次のプログラムでは5進数を入力する際に1桁ずつ分けて入力することにします。そのためにここでも配列を使いましょう。その名もズバリ keta という配列変数を設定することにします。
次のプログラムの3行目から8行目までで「5進数を1桁ずつ入力」しながら配列 keta に入れて、9行目から11行目までで「5進数を表示」しています。ここまでは人なら瞬時に無意識にやる部分ですが、機械相手だと意外にも手間がかかります。
12行目から15行目までで「各位の数×5ⁿ を足し続け」ながら10進数に変換しています。
i=0
keta=[]
while True: # ┐ ← 5進数を入力、当面続ける
n=input("1桁ずつ入力してください") # │
if n=="": # │
break # │ ← 空欄を入力したら、そこで終わり
keta.append(int(n)) # │ ← 配列変数を追加しながら、1桁ずつ入力する
i=i+1 # ┘
for j in range(i): # ┐
print(keta[j],end="") # │ ← 入力した5進数を表示する
print(end="(5)=") # ┘
s=0 # ┐ ← 初期値を 0 にして
for j in range(i): # │
s=s+keta[i-j-1]*5**j # │ ← 各位の数×5ⁿ を足し続ける
print (s,end="(10)") # ┘ 10進数で表示完了
では、ここから《課題》です。上の2つのプログラムを参考にして、次のプログラムを作ってください。
【 課題3つ 】
10進数の値とNの値を入力して、10進数をN進数に変換する
Mの値とM進数の値を入力して、M進数を10進数に変換する
M , Nの値とM進数の値を入力して、M進数をN進数に変換する
先ほど述べたように、実は「10進数を2進数に変換する」のと「5進数を10進数に変換する」のは似たような流れで組めるんですね。
そして、そのように組み立てていくと、結局は配列を使わなくても良くなります。
また【課題】の最後のもの(M進数をN進数に変換する)では同じような処理を2回実行することになりますから、関数を作って使い回すことも出来そうです。
では、がんばってください。やれるところまで、どうぞ。やれるものなら、どうぞ。
→ 10進数をN進数に変換する
→ M進数を10進数に変換する
→ M進数をN進数に変換する
私は次のように作ってみました。【課題】の最後のものだけお見せしますが、これが良いプログラムだとは限らないこと、再度申し添えます。
m=int(input("何進数? "))
print(m,end="進数の")
a=int(input("いくつ? "))
n=int(input("何進数の数に変換する? "))
def MtoN(m,a,n):
s=0
i=0
while a>0:
r=a%n
s=s+r*m**i
a=a//n
i=i+1
return s
print(a,"(",m,end=")=")
a=MtoN(m,a,10)
print(a,"(",10,end=")=")
a=MtoN(10,a,n)
print(a,"(",n,end=")")
このプログラムの実行例は次の通りです。123₍₅₎=38₍₁₀₎=1102₍₃₎ となりました。狙い通りの結果が出ました。
プログラミングとは一般化することだと言っても良いと思いますが、一般化が進むほど状況がシンプルになってくるんですね。この実習を通して生徒たちがそのことを感じてくれれば、大成功です。
◇ ◇ ◇
〜 Python で整数問題を腑に落とす 〜
▷ Python で 0.1 を足し続けたらどうなるか?
▷ Python でM進数をN進数に変換する
▷ Python で互除法を双方向で使ってみる