pythonで10進数からn進数に基数変換

rubyではNumeric#to_sに基数nを渡すとn進数での文字列表現を返してくれます。

1000000を2〜36進数で出力するコード

ruby

(2 .. 36).each do |e|
  p 10000000.to_s(e)
end

# => "100110001001011010000000"
# => "200211001102101"
# => "212021122000"
# => "10030000000"
# => "554200144"
# => "150666343"
# => "46113200"
# => "20731371"
# => "10000000"
# => "571016a"
# => "3423054"
# => "20c187a"
# => "148445a"
# => "d27e6a"
# => "989680"
# => "70c715"
# => "554c3a"
# => "40dhff"
# => "32a000"
# => "298gfa"
# => "1kf33a"
# => "1cgkde"
# => "16392g"
# => "10f000"
# => "lmona"
# => "im1ba"
# => "g7f2o"
# => "e40hh"
# => "cab3a"
# => "apkpk"
# => "9h5k0"
# => "8e8oa"
# => "7gehm"
# => "6n89a"
# => "5yc1s"

pythonで基数変換する関数としてはhexとかbinとかoctとか用意されてますが、7進数とか36進数とかやりたい場合は自前でやる必要があります。(多分)

python

print bin(10000000)
# => 0b100110001001011010000000
print oct(10000000)
# => 046113200
print hex(10000000)
# = >0x989680

そこでrubyと同じ感じで使える関数を書いてみました。

python

def base_str(n, radix):
    digits = "0123456789abcdefghijklmnopqrstuvwxyz"

    def num_check(attr, i):
        try:
            return int(i)
        except:
            raise ValueError('invalid %s : %s' % (attr, i))

    n = num_check('n', n)
    radix = num_check('radix', radix)

    if not 1 < radix < 37:
        raise ValueError('invalid radix %s' % radix)

    is_negative = n < 0
    n = abs(n)
    result = []

    while n:
        result.insert(0, n % radix)
        n /= radix
        if n == 0:
            break

    s = ''. join([digits[i] for i in result])
    if is_negative:
        s = '-' + s
    return s


使ってみた感じちゃんと同じ結果になっていると思う

for i in range (2, 37):
    print base_str(10000000, i)

# => 100110001001011010000000
# => 200211001102101
# => 212021122000
# => 10030000000
# => 554200144
# => 150666343
# => 46113200
# => 20731371
# => 10000000
# => 571016a
# => 3423054
# => 20c187a
# => 148445a
# => d27e6a
# => 989680
# => 70c715
# => 554c3a
# => 40dhff
# => 32a000
# => 298gfa
# => 1kf33a
# => 1cgkde
# => 16392g
# => 10f000
# => lmona
# => im1ba
# => g7f2o
# => e40hh
# => cab3a
# => apkpk
# => 9h5k0
# => 8e8oa
# => 7gehm
# => 6n89a
# => 5yc1s

余談

36進数とか個人的には使いどころがあまりない感じなんですが、こちらの本で紹介されている短縮URLサービスのサンプルに使われているのをみた覚えがあります。

Cloning Internet Applications With Ruby: Make Your Own Tinyurl, Twitter, Flickr, or Facebook Using Ruby

Cloning Internet Applications With Ruby: Make Your Own Tinyurl, Twitter, Flickr, or Facebook Using Ruby