所以我正在实现一个连分数库来处理二次整数和有理数的子集。连分数项由无符号整数表示。在处理连分数时,我注意到以下一般模式:
- 大多数术语都是小的个位数,其中 1 是最常见的。
- 有些术语可能很大,对于我的应用程序来说最大的可能是 366 位,但这些非常罕见。
- 较大的项表示一个特别好的数字近似,这意味着对于大部分而言,总体而言通常较少的项。
- 最坏的连分数是黄金比例,366 位精度的有理近似值大约对应于连续 525 个 1。
- 随机有理数通常不会有大量相同的数字,但可能有两到四个连续,其中 1 也是最常见的。
所以我对术语的数量和术语的大小都有限制,术语的数量与它们的大小大致成反比。所以将这些术语存储在机器字甚至字节中通常是非常浪费空间的,在最坏的情况下我仍然需要处理多字算术。鉴于术语大小和术语数量之间的大致反比关系(这两者都取决于分数的分子和分母的大小),我一直在尝试找到或提出一个好的压缩方案,这样我就不会浪费存储整数项的空间很大。
我考虑过Huffman encoding,因为编码和解码的速度很好,但我不确定如何得出代码值的概率。我有一种模糊的直觉,即Stern-Brocot 树可能会提供一个提示,因为它们是与连分数有直接关系的二叉树。
有谁知道一种很好的压缩方法来处理大量的小数字和偶尔的大数字,其中相同数字的运行通常很短(但在极少数情况下可能很长)?特别是我需要能够相当快地进行编码和解码(比如 O(n*lg(n)) 是我可以容忍的绝对最差的速度,O(n) 或更好),并且能够达到个别术语的位置,以便我知道我正在操作的术语编号(第四学期,第五学期等)。
另外,我对使用任何第三方实数或连分数库不感兴趣。我已经看过几个,它们要么不足以满足我的需求,要么过于矫枉过正,我想要自己编写代码以供我自己启迪的经验。
更新
我还了解了Gauss-Kuzmin 分布k
,它给出了随机数在 0 和 1 之间均匀分布的特定连分数项的概率分布。它是
P(k) = -lg(1.0 - 1.0/((k + 1.0)**2)
在 Python 伪代码中,其中 lg 是以 2 为底的对数。这是k
接近无穷大的极限,所以我的情况受到更多限制(尽管2**366
仍然很大)。Linas Vepstas 的“连分数的熵”给出了 Gauss-Kuzmin 分布的(信息)熵大约为 3.43 位。我的最大分母足够大,以至于我的连分数的信息熵可能接近该限制,尽管链接文章中的图表显示该限制的接近速度非常缓慢,因此对于相对较小的分母来说是不同的。