在Python中从十进制转换为任何基数

时间:2017-12-11 17:41:23

标签: python python-3.x base

此函数接受任何基数为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?

3 个答案:

答案 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。

除此之外,你必须得到某种自定义规则,复制字符或为它们添加前缀等。