我有this个整数序列。
它们之间的区别是随机的。但是,如果你计算每一个的差异,你可以看到它看起来有点对数函数(差异以对数方式增加)以某种方式与随机数/函数相关联。
我知道这不是一个庞大的数字,但我有数千个这样的系列(由相同的算法生成)。
我正在尝试尽可能多地压缩这些数据。我主要使用增量压缩,只能将数据压缩到原始大小的30%。
答案 0 :(得分:1)
(由相同算法生成)
然后该算法本身可能提供最佳压缩。它是什么?
除此之外,很容易将数据降低到大约10K字节。使用可变长度整数对差异进行编码。这样的整数表示为高位等于1的字节序列(任何数量的那些包括无),后面是高位等于零的一个字节。然后连接每个字节的低七位以获得整数。最重要的位首先出现。
这具有在单个字节中编码小于128的所有值的优点。超过96%的差异小于128.通用压缩器将有效地霍夫曼编码那些字节。
将其应用于差异,然后使用gzip -9
进行压缩,得到10626个字节。强制gzip算法仅使用Huffman压缩,我得到10018字节。如果我在第一个高位等于1之前剪切文件,仅使用Huffman分别压缩两个部分,然后将它们组合起来,得到9701个字节。
更新
以下是生成和解码变长整数的代码:
/* Write n as a variable-length integer to out. */
void var(unsigned long n, FILE *out)
{
int ch;
do {
ch = (int)(n & 0x7f);
n >>= 7;
if (n)
ch += 0x80;
putc(ch, out);
} while (n);
}
#define ULBITS 64 /* set to the number of bits in an unsigned long */
/* Read a variable-length integer from in, putting it in *n. Return 0 on
success, -1 on immediate end-of-file, -2 if end-of-file in the middle of an
integer, or 1 on overflow of the unsigned long type. */
int unvar(unsigned long *n, FILE *in)
{
int ch, b;
unsigned long d;
*n = 0;
b = 0;
do {
ch = getc(in);
if (ch == EOF)
return b ? -2 : -1;
if (b >= ULBITS)
return 1;
d = (unsigned long)(ch & 0x7f) << b;
if ((d >> b) != (ch & 0x7f))
return 1;
*n += d;
b += 7;
} while (ch & 0x80);
return 0;
}
答案 1 :(得分:0)
按当前存储,文件为101 KB。
如果将文件存储为32位整数序列(以二进制形式存储 - 是的,它们都足够小就可以执行此操作),这会使您降低到57 KB(14,345个整数x 4个字节)。 gzipping给你一个21 KB的文件。这已经超过了30%的边界,但我们可以做得更好!
如果您将每个连续差异存储为32位整数,则将其压缩为15 KB。
如果你想避免使用gzip,我们可以提出一些花哨的技巧。在每个差异上使用简单的Elias gamma coding生成一个14 KB的文件。但这需要一个烦人的比特流读写器,这可能是一个岔路口。
通过适当调整exp-Golomb code,您可以做得更好;我没试过。