【问题标题】:Convert from decimal to any base number in Python在 Python 中从十进制转换为任何基数
【发布时间】:2017-12-11 17:41:23
【问题描述】:

此函数接受任何以 10 为底的整数,并以指定的以 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 吗?

【问题讨论】:

  • 当您说“回到 base-10”时,您是在谈论从整数的 base-32 字符串表示形式转换为 Python int,对吗? (Python ints 不存储在 base 10 中,因此“base-10”部分有点误导。)
  • 是的,我就是这个意思:)
  • 只使用内置的base64.b32encode()有什么问题吗?
  • @zwer:我猜它不使用"0123456789qwertyuiopasdfghjklzxc"
  • @zwer 一切正常,但我想编写代码。

标签: python python-3.x base


【解决方案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 更好。

【讨论】:

  • 全力以赴并测试所有碱基:print(all(decodeN(encodeN(x, b), b) == x for b in range(2, 33) for x in range(10000)))
  • @MartijnPieters:我正要写这些测试。谢谢!
【解决方案2】:

你可以作弊:

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

【讨论】:

  • 非常感谢!最后一个答案对我来说是最好的,因为使用标准的字母顺序对我来说有点麻烦。
【解决方案3】:
>>> import string
>>> len(string.readable)
100

据此判断,您最多可以有 100 个基数,而不会出现重复字符或更改编码等问题。但是如果我们取出\t\n\r\x0b\x0c,我们会得到 94。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-24
    • 2019-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多