我需要对8字节的流进行编码,使得编码流中只有数字(0到9)。这是他们的任何标准编码机制吗?如果有多种方法可以做到这一点,哪一种方法在编码字符串的长度方面是有效的(越短越好)?
答案 0 :(得分:4)
将8个字节视为64位无符号整数并将其转换为十进制并用零填充到左侧。这应该是最短的字符串,因为它利用除起始字符之外的所有位置的所有可用数字。
如果您的数据不是均匀分布的,那么还有其他选择,可以查看霍夫曼编码,以便最常用的数据模式可以用较短的字符串表示。一种方法是使用第一个数字来编码字符串的长度。除第一个位置中的1之外的所有数字都可以视为长度说明符。这样,永远不会超过20位的最大长度。 (第20位只能是0或1,最高64位数是18,446,744,073,709,551,615。)其他数字到长度的精确解释映射应该基于模式的分布。如果您经常发生10种模式,您可以例如“0”表示一位代表一个完整的序列。
然而,任何这种更复杂的编码都会引入对更复杂的打包/解包代码的需求,甚至可能需要查找表,因此可能不值得付出努力。
答案 1 :(得分:4)
效率问题的答案将取决于 lot 对8字节块中典型值的范围。考虑Unicode的UTF-8和UTF-16。 UTF-8对于编码主要在西方脚本中编写的文本非常有效,因为这些脚本中的大多数字符都在0x00到0x7F的范围内,UTF-8可以将其存储在单个字节中。但是对于主要编写在东部脚本中的文本进行编码效率不高; UTF-16或UTF-32是更好的选择。
如果您已阅读the various UTFs,他们可能会激发解决方案。从根本上说,它们的工作方式就是允许将大量值直接编码到一个字节中,然后有一个标志(高位,我认为是UTF-8的第一个字节),表明byte不会告诉整个故事,并且需要下一个字节(或两个,或三个或四个)。起点是UTF-8的字节,UTF-16的一个字,但概念类似。
现在,你正在使用显着更小范围的值(0-9而不是0-255),显然我不建议尝试直接使用UTF,只是概念。例如,假设您的大多数值(直接或通过一些按摩)小于9000,相当多的小于9000000,并且只有罕见的值会超出该值。您可以采用UTF方法并说块(您的8字节值)被分成四位数段,并且每个编码块总是至少有一个段(四位)。如果第一个分段的值(aaaa)介于0000和8999之间(包括),则它是“终端”分段 - 这是实际值。但如果它是9aaa,那意味着有第二个段,你应该看一下aaabbbb(bbbb是下一个段的值)。如果 值介于0000000和8999999(含)之间,那么它就是一个终端;但如果它是9aabbbb,那就意味着看看aabbbbcccc(cccc是下一个片段);我想会给我们这个:
00000000000000000000-00000000000000008999 -> 4 digits (xxxx) 00000000000000009000-00000000000008999999 -> 8 digits (9xxxxxxx) 00000000000009000000-00000000008999999999 -> 12 digits (99xxxxxxxxxx) 00000000009000000000-00000008999999999999 -> 16 digits (999xxxxxxxxxxxxx) 00000009000000000000-00008999999999999999 -> 20 digits (9999xxxxxxxxxxxxxxxx) 00009000000000000000-08999999999999999999 -> 24 digits (99999xxxxxxxxxxxxxxxxxxx) 09000000000000000000-18446744073709551615 -> 28 digits (999999xxxxxxxxxxxxxxxxxxxxxx) Or special case, just use 26 digits for the last one: (999999xxxxxxxxxxxxxxxxxxxx)
你最好的情况是四位数,最差的是28或26,这取决于你是否想要特殊情况下块中的最后一个部分。比使用每个块的20位更好(可能)。
现在,这完全是袖手旁观,可能效率不高,但你明白了。反序列化非常容易,可能不那么难以序列化。
你可以看到为什么我开始评论你的典型值是什么。如果它们通常高于10,000,000,000,000,000,000,000,则上述不是直接编码它们的有效方式。但是,如果您的典型值处于高端而不是低端,则可以使用类似的技术,方法是在编码之前稍微按摩该值。
答案 2 :(得分:1)
具有最短长度的结果是直接将其转换为十进制。这导致最高值为18446744073709551615
,但如果没有任意长度整数功能,转换可能很困难。
下一个最长的是将其转换为八进制作为一个块。这导致最大长度为22,值为1777777777777777777777
。这只需转换即可转换,并且可以轻松处理。
下一个最长的是将其转换为八进制或十进制逐字节。这导致长度为24,分别重复8次377
或255
。来回转换是微不足道的,留给读者练习。