Python允许从给定基数的字符串中轻松创建一个整数
int(str, base).
我想执行相反的操作:从一个整数创建一个字符串,
例如,我想要一些函数int2base(num, base),这样:
int(int2base(x, b), b) == x
函数名/参数的顺序并不重要。
对于int()将接受的任何以b为底的数字x。
这是一个很容易写的函数:事实上,它比在这个问题中描述它更容易。然而,我觉得我一定是错过了什么。
我知道函数bin, oct, hex,但我不能使用它们的几个原因:
这些函数在旧版本的Python中不可用,我需要与(2.2)兼容
我想要一个通解对于不同的碱都可以用同样的方式表示
我想允许2 8 16以外的底数
相关的
Python优雅的int(string, base)逆函数
在python中使用递归的整数到base-x系统
Python中的Base 62转换
如何在Python中将整数转换为最短的url安全字符串?
下面是一个如何将任意基数转换为另一个基数的示例。
from collections import namedtuple
Test = namedtuple("Test", ["n", "from_base", "to_base", "expected"])
def convert(n: int, from_base: int, to_base: int) -> int:
digits = []
while n:
(n, r) = divmod(n, to_base)
digits.append(r)
return sum(from_base ** i * v for i, v in enumerate(digits))
if __name__ == "__main__":
tests = [
Test(32, 16, 10, 50),
Test(32, 20, 10, 62),
Test(1010, 2, 10, 10),
Test(8, 10, 8, 10),
Test(150, 100, 1000, 150),
Test(1500, 100, 10, 1050000),
]
for test in tests:
result = convert(*test[:-1])
assert result == test.expected, f"{test=}, {result=}"
print("PASSED!!!")
很棒的答案!
我想我问题的答案是“不”,我并没有错过一些明显的解决方案。
下面是我将使用的函数,它可以浓缩答案中所表达的好想法。
允许调用者提供的字符映射(允许base64编码)
检查负数和零
将复数映射为字符串元组
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
我写了这个函数,我用它来编码不同的碱基。我还提供了通过值“offset”来移动结果的方法。如果你想编码到64进制以上,但保持可显示字符(如95进制),这是有用的。
我还试图避免反转输出“列表”,并尽量减少计算操作。pow(base)数组是根据需要计算的,并保留用于对函数的其他调用。
输出是一个二进制字符串
pows = {}
######################################################
def encode_base(value,
base = 10,
offset = 0) :
"""
Encode value into a binary string, according to the desired base.
Input :
value : Any positive integer value
offset : Shift the encoding (eg : Starting at chr(32))
base : The base in which we'd like to encode the value
Return : Binary string
Example : with : offset = 32, base = 64
100 -> !D
200 -> #(
"""
# Determine the number of loops
try :
pb = pows[base]
except KeyError :
pb = pows[base] = {n : base ** n for n in range(0, 8) if n < 2 ** 48 -1}
for n in pb :
if value < pb[n] :
n -= 1
break
out = []
while n + 1 :
b = pb[n]
out.append(chr(offset + value // b))
n -= 1
value %= b
return ''.join(out).encode()
下面是一个如何将任意基数转换为另一个基数的示例。
from collections import namedtuple
Test = namedtuple("Test", ["n", "from_base", "to_base", "expected"])
def convert(n: int, from_base: int, to_base: int) -> int:
digits = []
while n:
(n, r) = divmod(n, to_base)
digits.append(r)
return sum(from_base ** i * v for i, v in enumerate(digits))
if __name__ == "__main__":
tests = [
Test(32, 16, 10, 50),
Test(32, 20, 10, 62),
Test(1010, 2, 10, 10),
Test(8, 10, 8, 10),
Test(150, 100, 1000, 150),
Test(1500, 100, 10, 1050000),
]
for test in tests:
result = convert(*test[:-1])
assert result == test.expected, f"{test=}, {result=}"
print("PASSED!!!")