在Python中用一个字符表示多个值



我有两个在0-31范围内的值。我希望能够用一个字符表示这两个值(例如,用64进制来解释我所说的1个字符是什么意思),但仍然能够知道这两个值是什么,以及哪个在前面。

找到一个具有1024个连续码点的不错的Unicode块,例如CJK Unified Ideographs,并将32*32的值映射到它们上。Python 3中:

def char_encode(a, b):
return chr(0x4E00 + a * 32 + b)
def char_decode(c):
return divmod(ord(c) - 0x4E00, 32)
print(char_encode(17, 3))
# => 倣
print(char_decode('倣'))
# => (17, 3)

当你提到Base64…这是不可能的。Base64编码中的每个字符只允许6位数据,而您需要10位来表示您的两个数字。

还要注意,虽然这只是一个字符,但它占用了两个或三个字节,这取决于您使用的编码。正如其他人所指出的,没有办法将10位数据塞进8位字节。


说明:a * 32 + b只是将[0,32)范围内的两个数映射为[0,1024)范围内的单个数。例如,0 * 32 + 0 = 0;31 * 32 + 31 = 1023chr找到具有该码点的Unicode字符,但具有低码点的字符如0是不可打印的,并且将是一个糟糕的选择,因此结果被转移到一个漂亮的大Unicode块的开始:0x4E0019968的十六进制表示,并且是CJK统一表意文字块中的第一个字符的码点。使用样例输入"17 * 32 + 3 = 547"、"19968 + 547 = 20515"或"0x5023"的十六进制形式,即字符""的码点。因此,chr(20515) = "倣".

char_decode函数只是反向执行所有这些操作:如果a * p + b = x,则a, b = divmod(x, p)(参见divmod)。如果是c = chr(x),则是x = ord(c)(参见ord)。我相信你知道如果w + r = y,那么r = y - w。在这个例子中,ord("倣") = 20515;20515 - 0x4E00 = 547;divmod(547, 32)(17, 3).

值[0,31]可以5位存储,从2**5 == 32开始。因此,您可以在10位中明确地存储两个这样的值。相反,除非其他条件成立,否则您将无法从少于10位的数据中明确地检索到两个5位的值。

如果您使用的编码允许1024或更多不同的字符,您可以将您的对映射到字符。否则你就做不到。所以ASCII不能在这里工作,Latin1也不能。但几乎所有的"正常"Unicode编码是可以的。

请记住,对于像UTF-8这样的东西,实际字符将占用超过10位。如果这是一个问题,请考虑使用UTF-16左右。

相关内容

  • 没有找到相关文章

最新更新