代码之家  ›  专栏  ›  技术社区  ›  Hemant

如何只使用数字(数字字符)对8字节块进行编码?

  •  0
  • Hemant  · 技术社区  · 14 年前

    我需要对8字节的流进行编码,以便编码的流中只有数字(0到9)。他们是否有任何标准的编码机制来实现这一点?如果有多种方法可以做到这一点,那么就编码字符串的长度而言,哪种方法更有效(越短越好)?

    3 回复  |  直到 14 年前
        1
  •  4
  •   Anders Abel    14 年前

    将8个字节视为64位无符号整数,然后将其转换为十进制,并用零填充到左侧。这应该是最短的字符串,因为它在所有位置都使用了除起始位置以外的所有可用数字。

    如果您的数据不是均匀分布的,那么还有其他的选择,可以研究哈夫曼编码,以便最常见的数据模式可以用较短的字符串表示。一种方法是使用第一个数字对字符串的长度进行编码。第一个位置中除1以外的所有数字都可以被视为长度说明符。这样就永远不会超过20位的最大长度。(第20位只能是0或1,最高的64位数字是18446744073709551615。)其他数字到长度的精确解释映射应基于您的模式分布。如果您有10个经常发生的模式,例如Reserv“0”表示一个数字代表一个完整的序列。

    然而,任何这种更复杂的编码都将引入对更复杂的打包/解包代码的需求,甚至可能需要查找表,因此可能不值得这样做。

        2
  •  4
  •   T.J. Crowder    14 年前

    效率问题的答案取决于 许多 关于8字节块中的典型值范围。考虑Unicode的utf-8和utf-16。UTF-8对于主要用西文脚本编写的文本编码非常有效,因为这些脚本中的大多数字符都在0x00到0x7F范围内,UTF-8可以存储在单个字节中。但是对于主要用东部脚本编写的文本,它的编码效率不是很高;在那里,UTF-16或UTF-32是更好的选择。

    如果你读到 the various UTFs 它们可能会激发解决方案。从根本上说,它们的工作方式是:允许许多值直接编码到一个字节中,然后有一个标志(在UTF-8的第一个字节中,我认为是高阶位),指示字节不能说明整个过程,并且需要下一个字节(或2、3或4)。UTF-8的起始点是一个字节,UTF-16的起始点是一个字,但是概念是相似的。

    现在,您正在与 戏剧性地 较小的值范围(0-9而不是0-255),显然我不建议直接使用UTF,只是概念。例如,假设你的大部分价值观(直接或通过一些按摩)低于9000,相当多的价值观低于900万,只有很少的价值观会带你走出去。您可以采用UTF方法,并说块(您的8字节值)被划分为四个数字段,并且每个编码块至少有一个段(四个数字)。如果第一段的值(a a a a a)介于0000和8999之间(包括0000和8999),则它是一个“终端”段-即实际值。但是如果是9a a,这意味着有第二个段,你应该看看aaabbb(bbbb是下一个段的值)。如果 那个 值在0000000到8999999之间(包括在内),它是一个终端;但如果它是9abbbb,则表示查看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位数字要好得多。

    现在,这是完全脱口而出,可能没有它可能的效率,但你得到了这个想法。反序列化非常容易,可能也不难序列化。

    你可以看到为什么我从评论你的典型值开始。如果它们通常高于10000000000000000,那么上面的方法不是直接编码它们的有效方法。但是,如果您的典型值位于高端而不是低端,则可以使用类似的技术,方法是在编码之前稍微按摩该值。

        3
  •  1
  •   Ignacio Vazquez-Abrams    14 年前

    长度最短的结果是直接将其转换为十进制。这导致了 18446744073709551615 但是,如果没有任意长度的整数功能,转换可能很困难。

    下一个最长的是将其转换为一个块的八进制。这将导致最大长度为22,值为 1777777777777777777777 . 这只需要转换换班,并且可以很容易地处理。

    下一个最长的是将它转换为八进制或十进制。这导致24个长度,8次重复 377 255 分别。来回转换是微不足道的,留给读者作为练习。