0.应用场景
笔者最近遇到了一个需求:需要将一个19位的十进制数映射为一个小于等于10位的编码。为了确保代码的优雅性和实现一对一的映射关系,笔者决定采用进制转换的思路来解决这个问题。
1.进制确定
先加假设进制数为X
,为了确保1对1的关系,我们需要确定的就是19位的十进制数能表示的所有19位数字的数量,也就是
(
1
0
19
−
1
)
−
1
0
18
(10^{19} - 1)-10^{18}
(1019−1)−1018(最大19位数-最小19位数); 要小于10位X进制所能表示的最大数
X
10
−
1
X^{10} - 1
X10−1(X进制最大10位数),
即:
(
1
0
19
−
1
)
−
1
0
18
<
X
10
−
1
(10^{19} - 1)-10^{18} < X^{10} - 1
(1019−1)−1018<X10−1
9 ⋅ 1 0 18 < X 10 9 \cdot 10^{18} < X^{10} 9⋅1018<X10
9 ⋅ 1 0 18 10 < X \sqrt[10]{9 \cdot 10^{18}} < X 109⋅1018<X
result = (9 * 10**18) ** (1/10)
print(result)
因此X最小取79进制。
接下来,我们需要确定如何表示 X 进制 的每一位。笔者首先考虑使用 ASCII 字符表,但发现其中包含一些不可打印的字符(如控制字符和空格),这会导致编码结果难以阅读和处理。因此,最终决定选取 93 个可见字符 作为 93 进制的符号集。(如下表)
ascii_printable = {
0: '!', 1: '"', 2: '#', 3: '$', 4: '%', 5: '&', 6: "'", 7: '(', 8: ')', 9: '*',
10: '+', 11: ',', 12: '-', 13: '.', 14: '/', 15: '0', 16: '1', 17: '2', 18: '3', 19: '4',
20: '5', 21: '6', 22: '7', 23: '8', 24: '9', 25: ':', 26: ';', 27: '<', 28: '=', 29: '>',
30: '?', 31: '@', 32: 'A', 33: 'B', 34: 'C', 35: 'D', 36: 'E', 37: 'F', 38: 'G', 39: 'H',
40: 'I', 41: 'J', 42: 'K', 43: 'L', 44: 'M', 45: 'N', 46: 'O', 47: 'P', 48: 'Q', 49: 'R',
50: 'S', 51: 'T', 52: 'U', 53: 'V', 54: 'W', 55: 'X', 56: 'Y', 57: 'Z', 58: '[', 59: '\\',
60: ']', 61: '^', 62: '_', 63: '`', 64: 'a', 65: 'b', 66: 'c', 67: 'd', 68: 'e', 69: 'f',
70: 'g', 71: 'h', 72: 'i', 73: 'j', 74: 'k', 75: 'l', 76: 'm', 77: 'n', 78: 'o', 79: 'p',
80: 'q', 81: 'r', 82: 's', 83: 't', 84: 'u', 85: 'v', 86: 'w', 87: 'x', 88: 'y', 89: 'z',
90: '{', 91: '|', 92: '}', 93: '~'
}
2.代码示例
# 定义可打印的 93 个字符(去掉空格和删除字符)
ascii_printable = [chr(i) for i in range(33, 127) if i != 127]
# 创建字符到值的映射字典
ascii_to_value = {char: idx for idx, char in enumerate(ascii_printable)}
# 将 10 进制数转换为 93 进制
def decimal_to_base93(n):
if n == 0:
return [0]
digits = []
while n > 0:
digits.append(n % 93)
n = n // 93
return digits[::-1] # 反转列表以得到正确的顺序
# 将 93 进制的每一位映射到 ASCII 字符
def base93_to_ascii(base93_digits):
return ''.join(ascii_printable[digit] for digit in base93_digits)
# 将 ASCII 字符串转换回 93 进制
def ascii_to_base93(ascii_str):
return [ascii_to_value[char] for char in ascii_str]
# 将 93 进制数转换回 10 进制数
def base93_to_decimal(base93_digits):
n = 0
for digit in base93_digits:
n = n * 93 + digit
return n
# 示例:将一个 19 位的 10 进制数转换为 93 进制的 10 位 ASCII 字符串
n = 1234567890123456789 # 替换为你的 19 位数字
base93_digits = decimal_to_base93(n)
ascii_result = base93_to_ascii(base93_digits)
print("93 进制表示:", base93_digits)
print("ASCII 表示:", ascii_result)
# 将 ASCII 字符串转换回 10 进制数
decoded_base93 = ascii_to_base93(ascii_result)
decoded_n = base93_to_decimal(decoded_base93)
print("解码后的 93 进制表示:", decoded_base93)
print("解码后的 10 进制数:", decoded_n)