Python позволяет легкое создание целого числа от строки данной основы через
int(str, base).
Я хочу выполнить инверсию: создание строки от целого числа, т.е. Я хочу некоторую функцию int2base(num, base)
, таким образом, что:
int(int2base(x, b), b) == x
Имя функции / порядок аргументов неважно.
Для любого числа x
и основа b
это int()
примет.
Это - легкая функция для записи: на самом деле это легче, чем описание его в этом вопросе. Однако я чувствую, что должен пропускать что-то.
Я знаю о функциях bin
, oct
, hex
, но я не могу использовать их по нескольким причинам:
Те функции не доступны на более старых версиях Python, с которым мне нужна совместимость с (2,2)
Я хочу общее решение, которое можно назвать тем же путем к различным основаниям
Я хочу позволить основания кроме 2, 8, 16
Если вам нужна совместимость с древними версиями Python, вы можете либо использовать gmpy (который действительно включает быструю, совершенно общую функцию преобразования int-to-string, и может быть построен для таких древних версий - возможно, вам придется попробовать более старые версии, так как последние не тестировались для старых версий 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 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
>>> 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'
Python не имеет встроенной функции для печати целого числа с произвольной базой. Если хотите, вам придется написать свой собственный.
def baseN(num,b,numerals="0123456789abcdefghijklmnopqrstuvwxyz"):
return ((num == 0) and numerals[0]) or (baseN(num // b, b, numerals).lstrip(numerals[0]) + numerals[num % b])
ref: http://code.activestate.com/recipes/65212/
Имейте в виду, что это может привести к
RuntimeError: maximum recursion depth exceeded in cmp
для очень больших целых чисел.
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