从十进制转换为 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.

除此之外,您还必须制定某种自定义规则,复制字符或为其添加前缀等。