如何压缩一个非重复数字大小的N位序列?

How to compress a sequence of non-repeated number size N bits?

本文关键字:数字 压缩 何压缩 一个      更新时间:2023-10-16

我试图压缩一个非负数序列,其中:

  • 每个数字的值范围是从 0 到 2^N-1
  • 每个数字只出现一次(这意味着总共有 2^N 个数字)

    N = 4 的示例:

    [14, 1, 8, 2, 12, 6, 0, 10, 4, 13, 5, 7, 15, 9, 3, 11]

因此,通常每个数字的成本为 4 位,对于 16 个数字,我们将不得不使用 16x4 = 64 位来存储它们。

目前我刚刚想到将它们压缩如下:

  • 对于前 8 个数字 ->使用 4 位来存储每个数字。
  • 接下来的 4 个数字--->每个数字只有 3 位/个
  • 对于接下来的 2 个数字--->每个数字只有 2 位/个
  • 对于接下来的 1 个数字--->只有 1 位。
  • 对于最后一个,
  • 实际上没有必要存储(显然,如果我们知道所有其他 15 个数字,我们应该知道最后一个数字是什么)

因此,压缩后的数据大小将是:

Z = 8 * 4 + 4 * 3 + 2 * 2 + 1 * 1 + 1 * 0 = 49 bits 

压缩比约为76%,这相当不错(我认为)。

但对于较大的 N 值,该比率似乎降低了(对于 N = 2048,该比率仅为 91%)

所以我想听听你对更好压缩的建议。

谢谢。

正如注释中指出的那样,如果所有排列的可能性相等,最佳编码是在排列枚举中用其索引替换整个排列。既然有n!可能的排列,索引需要对数2n!位,因此每个元素使用log 2n 位的朴素编码的压缩比为 (logn!/(n logn)。

使用斯特林的近似,我们可以将其重写为 (n log n - n + O(log n))/(n logn),即 1 - 1/(log n) + O(1/n),随着n的增长,它显然渐近接近 1。因此,对于较大的n,压缩比将不可避免地降低。

除非并非所有排列的可能性都相等(并且您有一些关于概率分布的信息),否则不可能实现更好的压缩。

目前您正在使用 N*2^N 位。

基本上你拥有的是数字的排列,每个排列都是唯一的,对于排列,你可以计算一个唯一的标识符。既然有(2^N)!排列,你只需要 ceil(log2((2^N)!)) 位。例如,这是 45 位。

对于这个特定问题,最有效的编码是在阶乘数系统中将[0 .. 2^N-1]的排列视为数字,并存储该排列的Lehmer码。

这就要求ceil(log2((2^N)!))位。对于 N = 4,这使用 45 位 (70.3%);对于 N = 11 (2^N = 2048),19581 位 (86.9%)。

压缩比随着N的增加而恶化;使用简单近似log x! >= (x log x) - x + 1我们达到1 - ((2^N - 1)/(2^N))*(1 / (N * log(2)))log2((2^N)!) / (N 2^N)的最小值,当N趋于无穷大时接近1

考虑到压缩比的绝对限制,任何你能找到的相当有效的方法都是值得的;对于小到N = 15的值,不可能超过90%。