【问题标题】:How can I compress a sequence of integers?如何压缩整数序列?
【发布时间】:2012-08-26 23:20:30
【问题描述】:

我有一个数组,其中包含 -255 到 +255 范围内的数据。例如数组可以是这样的:

  int data[]={234,56,-4,24,56,78,23,89,234,68,-12,-253,45,128};

在这里,解压缩时必须保留顺序,例如第一学期 234 之后,56 必须来。

那么,有什么方法可以压缩任何无法观察到任何重复模式的任意数字序列?

【问题讨论】:

  • 这正是 zip、gz 和其他压缩器解决的问题。
  • 使用通用压缩算法。例如。邮编。
  • 除了范围之外,你有没有关于数字序列的信息?如果它在该范围内基本上是随机的、均匀的分布,并且要保留顺序,那么您能做的最好的事情是每个条目大约 9 位。

标签: java arrays multidimensional-array arraylist compression


【解决方案1】:

-255 到 255 的范围意味着 511 个值 -> 9 位。如果单独取符号,符号1位,值1字节。

你可以把你的数组写成字节数组,每个字节值都是相关int的绝对值。

在一个单独的区域(一个长数组,或者可能是一个字节数组)中,存储符号位。

【讨论】:

  • 这是编码而不是压缩;压缩的唯一方法是去除冗余
  • 如果我可以对评论投反对票,我会的。无需悬疑:输出消耗的位数是否少于输入?是的
  • @NahuelFouilleul 压缩只是编码以使用更少的空间;除此之外,这会消除冗余吗?他正在消除 每个值不需要的 23 个额外位——这就是 redundancy is
【解决方案2】:

如果数据中确实没有模式,那么有用的压缩算法是不可能的。甚至不要费心尝试!

当然,在这种情况下,因为所有数字都在一个受限范围 n 中,所以您确实在位中有一个模式 - 即您的高位要么全为 0(正),要么全为 1(负)。

因此,如果您想合理有效地压缩(假设您有足够长的数字数组使其值得),像 zip 这样的标准压缩算法将起作用。

或者,您可以利用您有效地使用 9 位数字这一事实。因此,您可以通过将数字排列为一长串 9 位块并将其放入字节数组来推出自己的压缩算法。

【讨论】:

    【解决方案3】:

    在您的情况下(当无法观察到重复模式时),可变长度编码可能会对您有所帮助。

    例如,Elias gamma-codingExponential-Golomb coding一般的想法 - 小数字只需要很少的比特进行编码。 Exp-Golomb 编码用于 H.264/MPEG-4 AVC 视频压缩标准。用它对序列进行编码和解码非常容易,实现这种编码也不是很困难。

    编码所有整数的方法是建立一个双射,将整数 (0, 1, -1, 2, -2, 3, -3, ...) 映射到 (1, 2, 3, 4, 5, 6, 7, ...) 编码前。

    例如:

    序列(双射后)[ 0, 2, 5, 8, 5, 2 ] 将被编码为101100110000100100110011 - 如您所见 - 此序列中没有重复模式,但它仅使用 24 位编码。

    解码过程简述:

    1. 从输入流中读取并计算前导零位(直到找到非零 位)-> zero_bits_count

    2. 从输入流中读取下一个 ( zero_bits_count + 1 ) 位 -> 二进制

    3. 二进制转换为十进制

    4. 返回(十进制 - 1)

    1... -> no leading zeros, zero_bits_count = 0 -> read next 1 bit -> [1]... -> [1] is 1 -> 1 - 1 = 0

    011... -> [0] - one leading zero, zero_bits_count = 1 -> read next 2 bits -> [11]... -> [11] is 3 -> 3 - 1 = 2

    00110... -> [00] - two leading zeros, zero_bits_count = 2 -> read next 3 bits -> [110]... -> [110] is 6 -> 6 - 1 = 5

    等等

    【讨论】:

    • 但是在这个范围内[0,2,5,8,5,2],都没有。小于 16。因此每个数字需要 4 位。即总共需要 6*4=24 位。那么,压缩在哪里?
    • 如果值是均匀分布的,那么可变长度编码会将数据扩展为每个值大于 9 位。只有当较小的值比较大的值更有可能发生时,可变长度编码才有用。
    • @Debadyuti Maiti 我同意马克阿德勒的观点。这只是一种压缩序列的方法,其中有很多小值(但也存在大值)。在这种情况下,它会比使用预定义长度的编码更好(因为您需要为大值扩展代码长度,并且它也适用于小值)。
    • @Debadyuti Maiti 另一个例子:使用variable length 代码[0,2,5,8,5,2,255,3,4,20] -> 将被编码为60-bits 序列。但是,如果您决定为每个值使用具有固定长度的位串 -> 您将需要8-bit per value(因为值为 255)。而[0,2,5,8,5,2,255,3,4,20] 将被编码为80-bits 序列。只有经常出现小值时,您才会受益。
    【解决方案4】:

    如果数字本质上是随机且均匀分布的,并且要保留顺序,那么您可以做的最好的事情是每个符号大约 9 位。在 9 位时,将不使用单个 9 位值,即 2 的补码表示中的 -256。这很方便,因为您可以使用它作为结束符号来标记列表的结尾。然后你还编码了列表的长度,无论如何都需要它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-03
      • 2010-09-21
      • 1970-01-01
      • 2015-08-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多