技术

LZMA 压缩算法原理:区间编码与字面量上下文建模

📅 2026-10-13 · ✍️ 闪压技术团队 · ⏱ 4 分钟阅读

从"抄近路"到"记账本"

先把 LZMA 放回它所在的谱系里。它不是凭空冒出来的发明,而是 LZ 系算法和熵编码各走一段路之后,在某个点上会合的产物。

前半段它干的事,和 LZ77 算法核心:滑动窗口与字符串匹配原理 是一脉相承的——在已经处理过的内容里寻找重复,找到就用"往回跳多远、照抄多长"这种指令代替原文。区别在后半段:找到重复之后,那串指令该怎么写得尽可能短。

而这一段正是熵编码的地盘。所谓熵,粗略说是"信息在这个源头里有多随机",压缩的本质就是让输出序列比输入序列更少意外。

区间编码:把"范围"当容器

熵编码原理与霍夫曼编码算术编码:如何减少压缩冗余信息 里提到,霍夫曼编码的做法是给每个符号配一个码长。但码长是整数,这里就有个小尴尬——一个出现概率已经算低的符号,只要还需要一位来标记,就仍然实打实占掉一位。

区间编码换了个思路。它不分配码字,而是维护一个"范围",一个可以不断缩小的数值区间。编码时按各符号的概率把范围切成若干块,符号落进哪一块,范围就收缩到那一块。解码端做对称的事,靠一个游标在区间里比对,就知道当年写进去的是哪个符号。范围能缩得很细,不受整数位数的限制。

代价是运算量和状态都更重。它换来了更高的压缩效率,却没能全面取代霍夫曼。

字面量上下文:模型知道"上一个字节是谁"

光有好的编码器还不够,还得有好的模型。模型的任务很单纯:回答"下一个最可能出现的字节是什么"。

LZMA 的做法是分层。字面量字节不孤立编码,而是放进一组按位置编号的概率表里,用前文挑出该用哪一张。而"挑表"的依据是上下文片段——上一个字节的高位,乃至更往前的若干位片段。

为什么盯着高位?因为低位噪声大。文本文件里,一个字符的高位往往已经暗示了它的身份区间,拿高位当上下文既有效又省内存。这是 PPM 预测模型原理:用上下文猜下一个字节 那套思路的工程化版本:预测依赖上下文,上下文越具体,预测越准,剩下需要记录的不确定性就越少。

一条流水线,三种角色

串起来看就很清楚了:LZ 系负责"发现冗余",概率模型负责"预测",区间编码负责"记账"。三者是流水线关系,任何一环换掉,压缩效果和速度都会明显变化。

Zstandard 走的是同一条流水线的另一种配置,在速度上取向更明显,常被拿来做快速场景的默认选择。LZMA 这套组合偏保守,更愿意拿时间去换体积。

落到日常使用

理解了这条流水线,很多日常现象就顺理成章了。为什么有些文件怎么压都压不动——为什么有些文件压不动:压缩的极限在哪里 专门拆过这个话题。为什么同一份内容换个封装格式体积差别明显。为什么有的压缩包要耐心等。

闪压的 文件压缩 模块支持多种归档格式输出,不同格式背后就是不同的算法组合。想再往底层走一步,可以看看压缩包格式解析那类文章。

标签

技术

喜欢这篇?下载闪压试试

完全免费 · 本地处理 · 无广告

立即下载闪压
客服