从十进制转换为 Python 中的任何基数
Convert from decimal to any base number in Python
此函数接受任何以 10 为底的整数和 returns 该数字以其指定的 32 进制形式表示的字符串:
def encodeN(n,N,D="0123456789qwertyuiopasdfghjklzxc"):
return (encodeN(n//N,N)+D[n%N]).lstrip("0") if n>0 else "0"
示例:
print (encodeN(16002,32))
输出:
ya2
但是我在编写从 base-32 回 base-10 的解码函数时遇到问题。我怎么写呢?我可以输入自定义非标准字符来扩展 base-n 吗?
你可以作弊:
tmap = str.maketrans('qwertyuiopasdfghjklzxc', 'abcdefghijklmnopqrstuv')
result = int(inputvalue.translate(tmap), 32)
演示:
>>> tmap = str.maketrans('qwertyuiopasdfghjklzxc', 'abcdefghijklmnopqrstuv')
>>> inputvalue = 'ya2'
>>> int(inputvalue.translate(tmap), 32)
16002
int()
完全能够将任意基数转换回整数值;您需要做的就是使用标准的字母顺序。上面的 str.translate()
调用将您的自定义进度映射到标准。
否则,从输入字符串中取出每个字符,从左边开始,将其映射到字符映射中的整数,然后每次乘以底数 N:
def decodeN(n, N, D={c: i for i, c in enumerate("0123456789qwertyuiopasdfghjklzxc")}):
result = 0
for c in n:
result = (result * N) + D[c]
return result
这是较慢的选项; str.translate()
和 int()
都使用优化的 C 代码来完成它们的工作,并且总是比纯 python 方法更快。
将其转换为递归版本以匹配您的 encodeN()
实现:
def decodeN(n, N, D={c: i for i, c in enumerate("0123456789qwertyuiopasdfghjklzxc")}):
return decodeN(n[:-1], N) * N + D[n[-1]] if n else 0
使用相同的递归结构,你可以这样写:
def encodeN(n,N,D="0123456789qwertyuiopasdfghjklzxc"):
return (encodeN(n//N,N)+D[n%N]).lstrip("0") if n>0 else "0"
def decodeN(n,N,D="0123456789qwertyuiopasdfghjklzxc"):
return decodeN(n[:-1],N) * N + D.index(n[-1]) if n else 0
它似乎工作正常:
print(encodeN(16002, 32))
# "ya2"
print(decodeN("ya2", 32))
# 16002
print(all(decodeN(encodeN(x, b), b) == x for b in range(2, 33) for x in range(10000)))
# True
print(all(encodeN(decodeN(str(x),32), 32) == str(x) for b in range(2, 33) for x in range(10000)))
# True
虽然效率不高。使用 比使用 str.index
更好。
>>> import string
>>> len(string.readable)
100
据此判断,您最多可以以 100 为基数,而不会出现复制字符或更改编码等问题。但是如果我们去掉 \t\n\r\x0b\x0c
我们得到 94.
除此之外,您还必须制定某种自定义规则,复制字符或为其添加前缀等。
此函数接受任何以 10 为底的整数和 returns 该数字以其指定的 32 进制形式表示的字符串:
def encodeN(n,N,D="0123456789qwertyuiopasdfghjklzxc"):
return (encodeN(n//N,N)+D[n%N]).lstrip("0") if n>0 else "0"
示例:
print (encodeN(16002,32))
输出:
ya2
但是我在编写从 base-32 回 base-10 的解码函数时遇到问题。我怎么写呢?我可以输入自定义非标准字符来扩展 base-n 吗?
你可以作弊:
tmap = str.maketrans('qwertyuiopasdfghjklzxc', 'abcdefghijklmnopqrstuv')
result = int(inputvalue.translate(tmap), 32)
演示:
>>> tmap = str.maketrans('qwertyuiopasdfghjklzxc', 'abcdefghijklmnopqrstuv')
>>> inputvalue = 'ya2'
>>> int(inputvalue.translate(tmap), 32)
16002
int()
完全能够将任意基数转换回整数值;您需要做的就是使用标准的字母顺序。上面的 str.translate()
调用将您的自定义进度映射到标准。
否则,从输入字符串中取出每个字符,从左边开始,将其映射到字符映射中的整数,然后每次乘以底数 N:
def decodeN(n, N, D={c: i for i, c in enumerate("0123456789qwertyuiopasdfghjklzxc")}):
result = 0
for c in n:
result = (result * N) + D[c]
return result
这是较慢的选项; str.translate()
和 int()
都使用优化的 C 代码来完成它们的工作,并且总是比纯 python 方法更快。
将其转换为递归版本以匹配您的 encodeN()
实现:
def decodeN(n, N, D={c: i for i, c in enumerate("0123456789qwertyuiopasdfghjklzxc")}):
return decodeN(n[:-1], N) * N + D[n[-1]] if n else 0
使用相同的递归结构,你可以这样写:
def encodeN(n,N,D="0123456789qwertyuiopasdfghjklzxc"):
return (encodeN(n//N,N)+D[n%N]).lstrip("0") if n>0 else "0"
def decodeN(n,N,D="0123456789qwertyuiopasdfghjklzxc"):
return decodeN(n[:-1],N) * N + D.index(n[-1]) if n else 0
它似乎工作正常:
print(encodeN(16002, 32))
# "ya2"
print(decodeN("ya2", 32))
# 16002
print(all(decodeN(encodeN(x, b), b) == x for b in range(2, 33) for x in range(10000)))
# True
print(all(encodeN(decodeN(str(x),32), 32) == str(x) for b in range(2, 33) for x in range(10000)))
# True
虽然效率不高。使用 str.index
更好。
>>> import string
>>> len(string.readable)
100
据此判断,您最多可以以 100 为基数,而不会出现复制字符或更改编码等问题。但是如果我们去掉 \t\n\r\x0b\x0c
我们得到 94.
除此之外,您还必须制定某种自定义规则,复制字符或为其添加前缀等。