连续分数项的良好压缩方案?

时间:2015-08-21 19:56:47

标签: algorithm language-agnostic compression lossless-compression continued-fractions

所以我正在实施continued fraction库来处理quadratic integersrational numbers的子集。连续的分数项由无符号整数表示。在使用连续分数时,我注意到以下一般模式:

  1. 大多数术语都是小的单位数字,其中1是最常见的。
  2. 有些术语可能很大,我的应用程序最大可能是366位,但这些非常罕见。
  3. 一个较大的术语代表了一个特别好的数字近似值,这意味着大部分术语的总体术语通常较少。
  4. 最差可能的连续分数是黄金比例,而366位精度的理性近似对应于连续大约525 1。
  5. 随机有理数通常不会有相同数字的大量运行,但可能连续有两到四个,其中1也是最常见的。
  6. 因此我对术语数量和术语大小都有限制,术语数量与其大小大致成反比。因此,将这些术语存储在机器字或甚至字节中通常会浪费太多空间,我仍然需要在最坏的情况下处理多字算术。鉴于术语大小和术语数量之间的大致反比关系(这也取决于分数的分子和分母的大小),我一直试图找到或提出一个好的压缩方案,这样我就不会浪费这么多空间存储整数项。

    我考虑过Huffman encoding,因为编码和解码的速度很快,但我不确定如何提出代码值的概率。我有一种模糊的直觉,Stern-Brocot Trees可能提供一个提示,因为它们binary trees与连续分数有直接关系。

    有没有人知道一个很好的压缩方法来处理大量的小数字,而偶尔的大数字通常很短(但在极少数情况下可能很长)?特别是我需要能够相当快地编码和解码(比如O(n * lg(n))是我能忍受的绝对最差速度,最好是O(n)或更好),并且能够得到单个术语的位置,以便我知道我正在操作的术语编号(第四学期,第五学期等)。

    另外,我对使用任何第三方实数或连续分数库不感兴趣。我已经看了好几个,但它们不足以满足我的需求,而且我喜欢将自己编码的经验用于我自己的启发。

    更新

    我还了解到Gauss–Kuzmin distribution给出了k的特定连续分数项的概率分布,对于在0和1之间均匀分布的随机数。它是

    Python伪代码中的

    P(k) = -lg(1.0 - 1.0/((k + 1.0)**2),其中lg是基数2的对数。这是k接近无穷大的限制,所以我的情况稍微受到限制(尽管2**366仍然很大)。 Linas Vepstas的“The Entropy of Continued Fractions”将Gauss-Kuzmin分布的(信息)熵提供为大约3.43位。我的最大分母足够大,以至于我的连续分数的信息熵可能接近该限制,尽管链接文章中的图表显示极限接近非常缓慢,因此相对较小的分母也是如此。

5 个答案:

答案 0 :(得分:2)

一种可能性是简单的前缀码,其中二进制数1x具有编码为0的比特x - > 10和1 - > 11,然后是终结符0。

表:

1 -> 0
2 -> 100
3 -> 110
4 -> 10100
5 -> 10110
6 -> 11100
7 -> 11110
8 -> 1010100

此处针对n的相应霍夫曼代码概率类似于Theta(1 / n ^ 2)(因为字母表是无限的而挥舞着我的手)。

答案 1 :(得分:2)

您的发布似乎适合Rice Coding。您可以将编码参数(我们称之为 k )调整为您的数据。编码采用高于低 k 位的数字位,并发送多个1位,然后发送0.然后直接发送低 k 位。 / p>

答案 2 :(得分:1)

您可以使用arithmetic encoding将每个正整数视为源字母表中的符号。随着较大和较大整数的相对概率下降到零,无数是无关紧要的。

实际上,考虑到[0,1)上的均匀分布,您可以在连续分数展开中设置每个新整数a_n的条件概率(即来自熵源的每个新符号)为P(a_n = k)= 1 / k-1 /(k + 1)。你可能想要考虑第一个整数来理解为什么这个条件概率是有意义的(区间[0,1)中的一半数字将具有a_1 = 1,其中六分之一a_1 = 2,等等)。

此外,您可能需要将每个用于解码的新符号的算术编码方向翻转为明确的。不幸的是,算术en /解码不是很快。

答案 3 :(得分:1)

你可以考虑删除连续的分数,而是实现他们的变异表兄:continued logarithms。请参阅该论文的最底部,以讨论和实施基本算法。

甚至还有一个hardware implementation用于连续对数的大并行算术,具有与FFT相同的渐近复杂度,但是更简单,因此更低的常数。

如果您正在寻找比可逆{+, - ,*,/}运算符更具异国情调的东西,请参阅我的new question on the floor operator

正如您所见,对于非常大的整数或非常小的分数,连续分数往往会以术语位大小爆炸。在任何压缩方案中,您都需要利用小术语的巨大术语的振荡。

另一方面,持续的对数以一种递归的科学符号分割大项,'正如比尔·戈斯珀在那篇论文中提到的那样。每个术语共同例程仅发出或消耗非常小的消息,这些消息可以用自然类型的游程编码序列化形成,该序列化描述了将要描述的数字的对数库2.'

使用这种持续对数的不幸副作用是,Hurwitz数字是无模式的,而连续分数是非常规律的。然而,大多数(但不是全部)二次方冲突仍然是周期性的,也可以认为是压缩方案。

一旦采用紧凑的游程编码格式,您就可以使用传统的压缩技术来处理小数字,例如Mark Ransom在问题的评论中描述的LZW。

答案 4 :(得分:0)

另一种可能性是使用某种“通用编码”方案。由于随机选择的连续分数很少有很大的商,因此通用编码应该很有用。