本文共有 44 个字符:
the quick brown fox jumped over the lazy dog
相同的文本只需 11 个 Unicode 字符即可表示:
这是因为 ASCII 字符的范围是 1-27(如果您只使用此字符集中的 27 个字符,则基数为 27
abcdefghijklmnopqrstuvwxyz
),而 Unicode 字符的范围是 1-1114112,这意味着您可以在更大的内存中存储多个数字。如果您进行与指数相关的数学计算,则为数字。
例如,如果将每个字符转换为上述 27 个基本字符集中的索引,则文本
this
看起来像 [19, 7, 8, 18]
。如果您进行以下计算:
19 x 27 ^ 0 +
7 x 27 ^ 1 +
8 x 27 ^ 2 +
18 x 27 ^ 3 = 360334
您将获得一个唯一的数字
360334
,该数字恰好在 1-1114112 范围内,因此您可以执行 chr(360334)
来获取 Unicode 字符
。要返回,您可以执行 ord('')
来获得 360334
,您可以连续 divmod 来取回如下所示的数字:
360334 % 27 = 19
360334 // 27 = 13345
13345 % 27 = 7
13345 // 27 = 494
494 % 27 = 8
494 // 27 = 18
18 % 27 = 18
18 // 27 = 0 BREAK
问题是:如何在Python中将其作为转换和恢复函数?
这是我的尝试:
def power_sum(values, base, offset = 0):
return sum(value * base ** (index + offset) for index, value in enumerate(values))
def convert_text(text, chars):
base = len(chars)
chars = {char : index for index, char in enumerate(chars)}
temp = []
result = ''
for index, char in enumerate(text):
value = chars[char] # indexerror = missing that char in char set
if power_sum(temp, base, 1) + value > 0x10FFFF: # U+10FFFF is max unicode code point
result += chr(power_sum(temp, base))
temp = [value]
else:
temp.append(value)
result += chr(power_sum(temp, base))
return result
def revert_text(text, chars):
base = len(chars)
chars = list(chars)
result = ''
for char in text:
value = ord(char)
while value:
result += chars[int(value % base)]
value //= base
return result
chars = 'abcdefghijklmnopqrstuvwxyz '
print('Base:', len(chars), end = '\n\n')
texts = [
'this',
'the quick brown fox jumped over the lazy dog',
'china'
]
for text in texts:
print('Start text ({}): {}'.format(len(text), text))
text = convert_text(text, chars)
print('Unicode text ({}): {}'.format(len(text), text))
text = revert_text(text, chars)
print('Revert text ({}): {}'.format(len(text), text), end = '\n\n')
输出:
Base: 27
Start text (4): this
Unicode text (1):
Revert text (4): this
Start text (44): the quick brown fox jumped over the lazy dog
Unicode text (11): 늺🖛
Revert text (44): the quick brown fox jumped over the lazy dog
Start text (5): china
Unicode text (2):
Revert text (4): chin
由于某种原因,字符串
china
失败了。
不评论这种“压缩”的想法和原理(会有一些评论。但这不是你的问题)。
但是看看如何编码字符串“aaa”。
以 27 为基数,它是
27²×0 + 27×0 + 0
所以,0,对吗?
但这也是“a”的代码。或者“啊啊啊啊”。
由于您为最后一个字符添加了更多权重(不知何故,您在编码中是“小尾数”),因此您的情况与十进制数相同,但顺序相反(十进制数是“大尾数”)。 我的意思是,在十进制数中,开头的 0 表示较少。 001234 与 01234 或 1234 是一样的(在日常十进制中。不是在 C 或 python 中,它会触发八进制(对于 C)或者是语法错误(对于 python))。
在你的基数中,它的尾随 0 (或
a
)是没有意义的。所以 china
与 chin
或 chinaaaaa
是一样的。