我有这个排序的整数序列。
它们之间的差异是随机的。但是,如果您计算每个变量的差异,您会发现它看起来有点与随机数/函数相关的对数函数(差异以对数方式增加)。
我知道这不是一个庞大的数字,但我有成千上万个这样的系列(由相同的算法生成)。
我正在尝试尽可能多地压缩这些数据。我主要使用增量压缩,只能将数据压缩到其原始大小的 30%。
我有这个排序的整数序列。
它们之间的差异是随机的。但是,如果您计算每个变量的差异,您会发现它看起来有点与随机数/函数相关的对数函数(差异以对数方式增加)。
我知道这不是一个庞大的数字,但我有成千上万个这样的系列(由相同的算法生成)。
我正在尝试尽可能多地压缩这些数据。我主要使用增量压缩,只能将数据压缩到其原始大小的 30%。
(由相同的算法生成)
那么该算法本身可能会提供最佳压缩。它是什么?
除此之外,很容易将数据减少到大约 10K 字节。用可变长度整数编码差异。这样的整数表示为高位等于 1 的字节序列(任何数量的字节,包括无),后跟一个高位等于 0 的字节。然后连接每个字节的低七位得到整数。最低有效位首先出现。
这具有将小于 128 的所有值编码在单个字节中的优点。超过 96% 的差异小于 128。然后,通用压缩器将有效地对这些字节进行 Huffman 编码。
将其应用于您的差异,然后使用 压缩gzip -9
,我得到 10626 字节。强制 gzip 算法仅使用 Huffman 压缩,我得到 10018 字节。如果我在第一个高位等于一个之前剪切文件,仅使用 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;
}
当前存储的文件为 101 KB。
如果您将文件存储为 32 位整数序列(以二进制形式 - 是的,它们都足够小,可以执行此操作),那么您的大小将降至 57 KB(14,345 个整数 x 4 字节)。gzipping 会为您提供 21 KB 的文件。这已经超过了 30% 的界限,但我们可以做得更好!
如果您将每个连续的差异存储为 32 位整数,则 gzip 压缩到 15 KB。
如果你想避免 gzip,我们可以拿出一些花哨的技巧。对每个差异使用简单的Elias 伽马编码会生成一个 14 KB 的文件。但是,这需要一个烦人的比特流读取器/写入器,这可能是一个关闭。
使用适当调整的 exp-Golomb 代码,您可能会做得更好;我没试过。