此函数接受任何基数为10的整数,并以指定的base-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?
答案 0 :(得分:4)
你可以作弊:
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
答案 1 :(得分:1)
使用相同的递归结构,您可以写:
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
虽然效率不高。使用dict like MartijnPieters比使用str.index
更好。
答案 2 :(得分:1)
>>> import string
>>> len(string.readable)
100
从这个角度来看,你可以达到100基础而不会出现重复字符或更改编码等问题。但如果我们取出\t\n\r\x0b\x0c
,我们就会达到94。
除此之外,你必须得到某种自定义规则,复制字符或为它们添加前缀等。