Pythonでは、指定されたベースの文字列から整数を簡単に作成できます。
int(str, base).
私は逆を実行したい:整数からの文字列の作成、つまり、次のような関数int2base(num, base)
が必要です:
int(int2base(x, b), b) == x
関数名/引数の順序は重要ではありません。
int()
が受け入れる任意の数x
およびベースb
に対して。
これは簡単に記述できる関数です。実際、この質問で説明するよりも簡単です。しかし、私は何かを見逃しているに違いないと感じています。
関数bin
、oct
、hex
については知っていますが、いくつかの理由で使用できません。
これらの関数は古いバージョンのPythonでは利用できません。(2.2)
異なるベースに対して同じ方法で呼び出すことができる一般的なソリューションが必要です
2、8、16以外のベースを許可したい
Pythonの古いバージョンとの互換性が必要な場合は、 gmpy (高速で完全に一般的なintから文字列への変換関数を含み、そのような古いバージョン用にビルドできます)のいずれかを使用できます最近のリリースは、由緒あるPythonおよびGMPリリースではテストされていないため、古いリリースを試してみる必要があるかもしれませんが、速度は遅くなりますが、利便性はPythonコード-例えば、最も単純な例:
import string
digs = string.digits + string.ascii_letters
def int2base(x, base):
if x < 0:
sign = -1
Elif x == 0:
return digs[0]
else:
sign = 1
x *= sign
digits = []
while x:
digits.append(digs[int(x % base)])
x = int(x / base)
if sign < 0:
digits.append('-')
digits.reverse()
return ''.join(digits)
def baseN(num,b,numerals="0123456789abcdefghijklmnopqrstuvwxyz"):
return ((num == 0) and numerals[0]) or (baseN(num // b, b, numerals).lstrip(numerals[0]) + numerals[num % b])
参照: http://code.activestate.com/recipes/65212/
これにより、
RuntimeError: maximum recursion depth exceeded in cmp
非常に大きな整数の場合。
驚くべきことに、人々は小さなベース(英語のアルファベットの長さよりも小さい)に変換するソリューションのみを提供していました。 2から無限大までの任意のベースに変換するソリューションを提供する試みはありませんでした。
だからここに超簡単な解決策があります:
def numberToBase(n, b):
if n == 0:
return [0]
digits = []
while n:
digits.append(int(n % b))
n //= b
return digits[::-1]
そのため、超巨大な数値をベース577
に変換する必要がある場合、
numberToBase(67854 ** 15 - 102, 577)
、正しい解決策を提供します:[4, 473, 131, 96, 431, 285, 524, 486, 28, 23, 16, 82, 292, 538, 149, 25, 41, 483, 100, 517, 131, 28, 0, 435, 197, 264, 455]
、
後で必要なベースに変換できます
"{0:b}".format(100) # bin: 1100100
"{0:x}".format(100) # hex: 64
"{0:o}".format(100) # oct: 144
素晴らしい答えです!私の質問に対する答えは「いいえ」だったと思います。明らかな解決策を見逃していませんでした。これが、答えで表現された良いアイデアを凝縮する、私が使用する関数です。
def int2base(x,b,alphabet='0123456789abcdefghijklmnopqrstuvwxyz'):
'convert an integer to its string representation in a given base'
if b<2 or b>len(alphabet):
if b==64: # assume base64 rather than raise error
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
else:
raise AssertionError("int2base base out of range")
if isinstance(x,complex): # return a Tuple
return ( int2base(x.real,b,alphabet) , int2base(x.imag,b,alphabet) )
if x<=0:
if x==0:
return alphabet[0]
else:
return '-' + int2base(-x,b,alphabet)
# else x is non-negative real
rets=''
while x>0:
x,idx = divmod(x,b)
rets = alphabet[idx] + rets
return rets
Pythonには、任意の基数で整数を出力するための組み込み関数がありません。必要に応じて、独自に記述する必要があります。
私のプロジェクトからbaseconv.py
を使用できます: https://github.com/semente/python-baseconv
サンプル使用法:
>>> from baseconv import BaseConverter
>>> base20 = BaseConverter('0123456789abcdefghij')
>>> base20.encode(1234)
'31e'
>>> base20.decode('31e')
'1234'
>>> base20.encode(-1234)
'-31e'
>>> base20.decode('-31e')
'-1234'
>>> base11 = BaseConverter('0123456789-', sign='$')
>>> base11.encode('$1234')
'$-22'
>>> base11.decode('$-22')
'$1234'
たとえば、baseconv.base2
、baseconv.base16
、baseconv.base64
などのブルタンコンバーターがあります。
私はsimplify最も投票された答え に:
BS="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
def to_base(n, b):
return "0" if not n else to_base(n//b, b).lstrip("0") + BS[n%b]
非常に大きな整数と負の数のRuntimeError: maximum recursion depth exceeded in cmp
についても同じアドバイスがあります。 (使用できます sys.setrecursionlimit(new_limit)
)
再帰問題を回避する:
BS="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
def to_base(s, b):
res = ""
while s:
res+=BS[s%b]
s//= b
return res[::-1] or "0"
http://code.activestate.com/recipes/65212/
def base10toN(num,n):
"""Change a to a base-n number.
Up to base-36 is supported without special notation."""
num_rep={10:'a',
11:'b',
12:'c',
13:'d',
14:'e',
15:'f',
16:'g',
17:'h',
18:'i',
19:'j',
20:'k',
21:'l',
22:'m',
23:'n',
24:'o',
25:'p',
26:'q',
27:'r',
28:'s',
29:'t',
30:'u',
31:'v',
32:'w',
33:'x',
34:'y',
35:'z'}
new_num_string=''
current=num
while current!=0:
remainder=current%n
if 36>remainder>9:
remainder_string=num_rep[remainder]
Elif remainder>=36:
remainder_string='('+str(remainder)+')'
else:
remainder_string=str(remainder)
new_num_string=remainder_string+new_num_string
current=current/n
return new_num_string
同じリンクからの別のものはここにあります
def baseconvert(n, base):
"""convert positive decimal integer n to equivalent in another base (2-36)"""
digits = "0123456789abcdefghijklmnopqrstuvwxyz"
try:
n = int(n)
base = int(base)
except:
return ""
if n < 0 or base < 2 or base > 36:
return ""
s = ""
while 1:
r = n % base
s = digits[r] + s
n = n / base
if n == 0:
break
return s
このためにpipパッケージを作成しました。
Bases.pyを使用することをお勧めします https://github.com/kamijoutouma/bases.py bases.jsに触発された
from bases import Bases
bases = Bases()
bases.toBase16(200) // => 'c8'
bases.toBase(200, 16) // => 'c8'
bases.toBase62(99999) // => 'q0T'
bases.toBase(200, 62) // => 'q0T'
bases.toAlphabet(300, 'aAbBcC') // => 'Abba'
bases.fromBase16('c8') // => 200
bases.fromBase('c8', 16) // => 200
bases.fromBase62('q0T') // => 99999
bases.fromBase('q0T', 62) // => 99999
bases.fromAlphabet('Abba', 'aAbBcC') // => 300
https://github.com/kamijoutouma/bases.py#known-basesalphabets 使用可能なベースについて
def base(decimal ,base) :
list = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
other_base = ""
while decimal != 0 :
other_base = list[decimal % base] + other_base
decimal = decimal / base
if other_base == "":
other_base = "0"
return other_base
print base(31 ,16)
出力:
「1F」
>>> numpy.base_repr(10, base=3) '101'
num = input("number")
power = 0
num = int(num)
while num > 10:
num = num / 10
power += 1
print(str(round(num, 2)) + "^" + str(power))
>>> import string
>>> def int2base(integer, base):
if not integer: return '0'
sign = 1 if integer > 0 else -1
alphanum = string.digits + string.ascii_lowercase
nums = alphanum[:base]
res = ''
integer *= sign
while integer:
integer, mod = divmod(integer, base)
res += nums[mod]
return ('' if sign == 1 else '-') + res[::-1]
>>> int2base(-15645, 23)
'-16d5'
>>> int2base(213, 21)
'a3'
def int2base(a, base, numerals="0123456789abcdefghijklmnopqrstuvwxyz"):
baseit = lambda a=a, b=base: (not a) and numerals[0] or baseit(a-a%b,b*base)+numerals[a%b%(base-1) or (a%b) and (base-1)]
return baseit()
どのベースでも、すべての数値はa1+a2*base**2+a3*base**3...
に等しくなります。「ミッション」はすべてのaを見つけることです。
EveryN=1,2,3...
の場合、コードはb=base**(N+1)
をbで「取り消す」ことでaN*base**N
を分離し、aをすべてNより大きくスライスし、aのすべてをスライスします。現在のaN*base**N
。
Base%(base-1)== 1 base ** p%(base-1)== 1の場合、q * base ^ p%(base-1)== qの場合、q = base-1の場合は例外が1つのみ0を返します。0を返す場合に修正するために、funcは最初から0をチェックしています。
このサンプルでは、(除算ではなく)1回の乗算と、比較的短い時間で実行される一部のモジュールがあります。
興味のある人のための再帰的なソリューション。もちろん、これは負のバイナリ値では機能しません。 Two's Complementを実装する必要があります。
def generateBase36Alphabet():
return ''.join([str(i) for i in range(10)]+[chr(i+65) for i in range(26)])
def generateAlphabet(base):
return generateBase36Alphabet()[:base]
def intToStr(n, base, alphabet):
def toStr(n, base, alphabet):
return alphabet[n] if n < base else toStr(n//base,base,alphabet) + alphabet[n%base]
return ('-' if n < 0 else '') + toStr(abs(n), base, alphabet)
print('{} -> {}'.format(-31, intToStr(-31, 16, generateAlphabet(16)))) # -31 -> -1F
別の短いもの(そして理解しやすいimo):
def int_to_str(n, b, symbols='0123456789abcdefghijklmnopqrstuvwxyz'):
return (int_to_str(n/b, b, symbols) if n >= b else "") + symbols[n%b]
そして、適切な例外処理により:
def int_to_str(n, b, symbols='0123456789abcdefghijklmnopqrstuvwxyz'):
try:
return (int_to_str(n/b, b) if n >= b else "") + symbols[n%b]
except IndexError:
raise ValueError(
"The symbols provided are not enough to represent this number in "
"this base")
これは、符号付き整数とカスタム数字を処理する再帰バージョンです。
import string
def base_convert(x, base, digits=None):
"""Convert integer `x` from base 10 to base `base` using `digits` characters as digits.
If `digits` is omitted, it will use decimal digits + lowercase letters + uppercase letters.
"""
digits = digits or (string.digits + string.ascii_letters)
assert 2 <= base <= len(digits), "Unsupported base: {}".format(base)
if x == 0:
return digits[0]
sign = '-' if x < 0 else ''
x = abs(x)
first_digits = base_convert(x // base, base, digits).lstrip(digits[0])
return sign + first_digits + digits[x % base]
def baseConverter(x, b):
s = ""
d = string.printable.upper()
while x > 0:
s += d[x%b]
x = x / b
return s[::-1]
def dec_to_radix(input, to_radix=2, power=None):
if not isinstance(input, int):
raise TypeError('Not an integer!')
Elif power is None:
power = 1
if input == 0:
return 0
else:
remainder = input % to_radix**power
digit = str(int(remainder/to_radix**(power-1)))
return int(str(dec_to_radix(input-remainder, to_radix, power+1)) + digit)
def radix_to_dec(input, from_radix):
if not isinstance(input, int):
raise TypeError('Not an integer!')
return sum(int(digit)*(from_radix**power) for power, digit in enumerate(str(input)[::-1]))
def radix_to_radix(input, from_radix=10, to_radix=2, power=None):
dec = radix_to_dec(input, from_radix)
return dec_to_radix(dec, to_radix, power)
別のソリューションは、ベース2〜10で動作し、より高いベースの場合は変更が必要です。
def n2b(n, b):
if n == 0:
return 0
d = []
while n:
d.append(int(n % b))
n /= b
return ''.join(map(str,d[::-1]))
例:
n2b(10,2) => '10100'
int(n2b(10,2),2) => 10
数字を表すための唯一の選択肢は文字列ではありません。整数のリストを使用して各桁の順序を表すことができます。これらは簡単に文字列に変換できます。
いずれの回答も、ベース<2を拒否しません。ほとんどの場合、非常に遅く実行されるか、非常に大きい数(56789 ** 43210など)のスタックオーバーフローでクラッシュします。このような障害を回避するには、次のようにすばやく減らします。
def n_to_base(n, b):
if b < 2: raise # invalid base
if abs(n) < b: return [n]
ret = [y for d in n_to_base(n, b*b) for y in divmod(d, b)]
return ret[1:] if ret[0] == 0 else ret # remove leading zeros
def base_to_n(v, b):
h = len(v) // 2
if h == 0: return v[0]
return base_to_n(v[:-h], b) * (b**h) + base_to_n(v[-h:], b)
assert ''.join(['0123456789'[x] for x in n_to_base(56789**43210,10)])==str(56789**43210)
速度的には、n_to_base
は大きな数(私のマシンでは約0.3秒)でstr
と同等ですが、hex
と比較すると驚くかもしれません(私のマシンでは約0.3ms、または1000倍高速)。その理由は、大きな整数がベース256(バイト)でメモリに格納されるためです。各バイトは、単純に2文字の16進文字列に変換できます。この整列は、2の累乗であるベースに対してのみ発生します。そのため、2、8、および16(およびbase64、ascii、utf16、utf32)には特別なケースがあります。
10進数文字列の最後の桁を考慮してください。整数を形成するバイトシーケンスとどのように関連していますか? s[i]
が最下位(リトルエンディアン)であるバイトs[0]
にラベルを付けましょう。その場合、最後の桁はsum([s[i]*(256**i) % 10 for i in range(n)])
です。さて、256 ** iが6 for i> 0(6 * 6 = 36)で終わるため、最後の桁が(s[0]*5 + sum(s)*6)%10
になります。これから、最後の桁がすべてのバイトの合計に依存していることがわかります。この非ローカルプロパティは、10進数への変換を困難にするものです。