【Python】記数法の変換(10進数⇔n進数)

PythonのTopに戻る


 

 $n$進数から$10$進数へ変換

int関数の2つ目の引数として整数を指定すると基数を指定できる。(‘100’, 2) とすると$2$進数表記における$100$を$10$進数表記に変換する。

print(int('100', 2))
# 4
print(int('100', 3))
# 9
print(int('100', 4))
# 16
print(int('100', 8))
# 64
print(int('100', 16))
# 256

2つ目の引数には$2$~$36$までの整数を指定しなければならない。それ以外の整数を書いた場合は以下のようなエラーが出る。

ValueError: int() base must be >= 2 and <= 36, or 0

また、1つ目の引数には文字列を指定しなければならない。ただし文字列であっても “100.0” のように整数型でないと invalid literal だと言われて怒られる。

ところで、なぜ$36$進法までしか変換できないのかというと、単純に数字とアルファベットの数が足りなくなるためである。

 

 $10$進数から$n$進数へ変換

上で$n$進数表記における整数を$10$進数表記に変換するのはint関数で可能であることを確認した。反対に$10$進数を$2$進数、$8$進数、$16$進数のそれぞれに変換するには以下のようにする。

x = 10
print(bin(x))
# 0b1010
print(oct(x))
# 0o12
print(hex(x))
# 0xa

この返り値には「0b」といった接頭辞が付く。

$10$進数表記の整数を$2$~$9$を基数とする任意の記数法に変換する方法は自作する必要がある。

def base10int(value, base):
    if (int(value / base)):
        return base10int(int(value / base), base) + str(value % base)
    return str(value % base)

print(base10int(100, 4))
# 1210

上の例では十進法表記における100を4進数に変換している。あるいは以下のようにリスト化しても良い。やっていることは上と同じだが、各位の数字が少し扱いやすくなる。

def base10int(value, base):
    upper = value > base and base10int(value // base, base) or []
    return upper + [value % base]  # リストの結合

print(base10int(100, 4))
# [1, 2, 1, 0]

ただし上の方法は基数が2桁の場合は使用できない。十進法表記された整数を$2$~$36$までの整数を基数とする記数法に変換するには、numpyライブラリのbase_repr関数を利用するのが手っ取り早い。負値を渡しても問題無く動作する。

import numpy as np

print(np.base_repr(10, 7))
# 13
print(np.base_repr(13, 15))
# D
print(np.base_repr(-130, 20))
# -6A
print(np.base_repr(100, 36))
# 2S

残念ながらbase_repr関数は小数を変換できないため、小数も含めて基数を変換したい場合は本格的に関数を自作する必要がある。やるべきことは単なる剰余計算なので、やや面倒ではあるが理屈が分かっていれば実装は可能である。

例外的に、組み込み関数を利用して16進数を変換することは可能。hex関数は10進数を16進数表示に、fromhex関数は16進数を10進数表示に変換する。

#16進数↔10進数

print(float.hex(0.25))
# 0x1.0000000000000p-2
print(float.hex(24.9))
# 0x1.8e66666666666p+4
print(float.fromhex("46.A5"))
# 70.64453125
print(float.fromhex("1A.7CD"))
# 26.487548828125

hex関数は実数を受け取り、fromhex関数は文字列型の実数を受け取る。hex関数の返り値の「p+4」などの数字は$2$の指数を表している。

 

 $n>36$ の場合

上で見たように $n>36$ の場合はnumpyの組み込み関数が対応していないため、各位の数をリストに格納する関数を自作する必要がある。

def Dec_to_N(num, base):
    if num >= base:
        yield from Dec_to_N(num // base, base)
    yield num % base

def N_to_Dec(digits, base):
    num = 0
    for digit in digits:
        num = num * base + digit
    return num

num = 4649
base = 39
digits = list(Dec_to_N(num, base))
print(digits)
# [3, 2, 8]

print(N_to_Dec(digits, base))
# 4649 (元の十進数)

Dec_to_N は十進数を$n$進数に、N_to_Dec は$n$進数を十進数にそれぞれ変換する。ただし小数には対応していないので注意。

 


【参考】List of reverse divisors in various bases


PythonのTopに戻る