<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>编码算法 on Snow</title>
        <link>https://SymphonyW.github.io/tags/%E7%BC%96%E7%A0%81%E7%AE%97%E6%B3%95/</link>
        <description>Recent content in 编码算法 on Snow</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>en</language>
        <copyright>Snow</copyright>
        <lastBuildDate>Thu, 15 Oct 2026 20:30:00 +0800</lastBuildDate><atom:link href="https://SymphonyW.github.io/tags/%E7%BC%96%E7%A0%81%E7%AE%97%E6%B3%95/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>Entropy Coding and File Compression: Distinctions, Common Methods, and the Role of Local Continuity</title>
        <link>https://SymphonyW.github.io/p/entropy-coding-and-file-compression/</link>
        <pubDate>Thu, 15 Oct 2026 20:30:00 +0800</pubDate>
        
        <guid>https://SymphonyW.github.io/p/entropy-coding-and-file-compression/</guid>
        <description>&lt;img src="https://SymphonyW.github.io/p/entropy-coding-and-file-compression/bg.svg" alt="Featured image of post Entropy Coding and File Compression: Distinctions, Common Methods, and the Role of Local Continuity" /&gt;&lt;h1 id=&#34;熵编码与文件压缩区别常见方法与局部连续性的作用&#34;&gt;熵编码与文件压缩：区别、常见方法与局部连续性的作用
&lt;/h1&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;熵编码是“怎样用更少的比特表示一串符号”，文件压缩是“怎样把整个文件变得更小”。&lt;/strong&gt; 前者通常是后者的最后一环，而不是与后者平级的概念。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href=&#34;https://SymphonyW.github.io/p/entropy-coding-and-file-compression/bg.svg&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;img src=&#34;https://SymphonyW.github.io/p/entropy-coding-and-file-compression/bg.svg&#34; alt=&#34;熵编码与文件压缩的关系&#34; loading=&#34;lazy&#34; decoding=&#34;async&#34;&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;先看最容易混淆的结论：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;问题&lt;/th&gt;
&lt;th&gt;简短答案&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Huffman、Arithmetic、ANS 是什么&lt;/td&gt;
&lt;td&gt;熵编码器：依据符号概率分配比特&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RLE、LZ77、LZW、Delta、Prediction 是什么&lt;/td&gt;
&lt;td&gt;建模、变换或消除重复的方法，不是狭义熵编码&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ZIP、gzip、PNG、JPEG、Zstandard 是什么&lt;/td&gt;
&lt;td&gt;完整格式或压缩方案，内部通常组合多种方法&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;量化是不是熵编码&lt;/td&gt;
&lt;td&gt;不是；量化会降低精度，通常是有损压缩的主要来源&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;局部连续为什么有用&lt;/td&gt;
&lt;td&gt;它让相邻值更可预测，使差值、残差、游程或变换系数更集中&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;连续性会直接降低零阶熵吗&lt;/td&gt;
&lt;td&gt;不一定；若符号计数不变，静态无上下文熵编码甚至完全看不出顺序变化&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;a href=&#34;https://SymphonyW.github.io/p/entropy-coding-and-file-compression/compression-pipeline.svg&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;img src=&#34;https://SymphonyW.github.io/p/entropy-coding-and-file-compression/compression-pipeline.svg&#34; alt=&#34;完整压缩流水线与熵编码所在位置&#34; loading=&#34;lazy&#34; decoding=&#34;async&#34;&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;一条典型压缩链路可以写成：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;原始数据
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  → 重排 / 分块 / 预测 / 字典匹配 / 变换
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  → 可选的量化（有损）
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  → 产生符号：字面量、长度、距离、残差、系数……
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  → 概率建模
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  → 熵编码
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  → 文件头、码表、索引、校验和与容器封装
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;其中每一层解决的问题不同：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;层次&lt;/th&gt;
&lt;th&gt;解决什么问题&lt;/th&gt;
&lt;th&gt;典型方法&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;建模与去冗余&lt;/td&gt;
&lt;td&gt;找到重复、相关性和可预测性&lt;/td&gt;
&lt;td&gt;RLE、LZ77、LZW、预测、Delta、BWT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;数据变换&lt;/td&gt;
&lt;td&gt;把信息集中到更容易编码的位置&lt;/td&gt;
&lt;td&gt;DCT、小波、颜色变换、MTF、字节重排&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;量化&lt;/td&gt;
&lt;td&gt;主动丢掉不重要的信息&lt;/td&gt;
&lt;td&gt;JPEG 系数量化、音视频感知量化&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;概率建模&lt;/td&gt;
&lt;td&gt;估计“下一个符号多可能出现”&lt;/td&gt;
&lt;td&gt;频率表、上下文模型、自适应模型&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;熵编码&lt;/td&gt;
&lt;td&gt;按概率把符号映射为比特&lt;/td&gt;
&lt;td&gt;Huffman、Arithmetic、Range、ANS、Rice&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;文件封装&lt;/td&gt;
&lt;td&gt;让结果可保存、校验、随机访问和解码&lt;/td&gt;
&lt;td&gt;Header、码表、块索引、CRC、元数据&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;因此，&lt;strong&gt;文件压缩关心端到端结果，熵编码只关心给定符号及其概率后如何接近理论码长。&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&#34;从信息量到熵&#34;&gt;从“信息量”到“熵”
&lt;/h2&gt;&lt;p&gt;如果一个符号出现的概率为 $p(x)$，它携带的信息量定义为：&lt;/p&gt;
&lt;p&gt;$$
I(x)=-\log_2 p(x)
$$&lt;/p&gt;
&lt;p&gt;越常见的符号越“不意外”，需要的比特越少；越罕见的符号越意外，需要的比特越多。例如：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:right&#34;&gt;符号概率&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;理想信息量&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:right&#34;&gt;$1/2$&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;1 bit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:right&#34;&gt;$1/4$&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;2 bits&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:right&#34;&gt;$1/8$&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;3 bits&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:right&#34;&gt;$1/1000$&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;约 9.97 bits&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;信源的平均信息量就是熵：&lt;/p&gt;
&lt;p&gt;$$
H(X)=-\sum_x p(x)\log_2p(x)
$$&lt;/p&gt;
&lt;p&gt;假设四个符号的概率分别是 $0.5、0.25、0.125、0.125$，那么：&lt;/p&gt;
&lt;p&gt;$$
H(X)=0.5\times1+0.25\times2+0.125\times3+0.125\times3=1.75\ \text{bit/符号}
$$&lt;/p&gt;
&lt;p&gt;这意味着：如果符号确实服从这个分布，足够长的序列平均很难低于 1.75 bit/符号。熵编码的目标，就是让实际平均码长尽量靠近这个值。&lt;/p&gt;
&lt;p&gt;但编码器通常拿不到真实分布 $p$，只能使用模型估计出的 $q$。这时理想平均码长对应交叉熵：&lt;/p&gt;
&lt;p&gt;$$
H(p,q)=H(p)+D_{KL}(p\Vert q)
$$&lt;/p&gt;
&lt;p&gt;$D_{KL}$ 是模型失配带来的额外代价。这个公式揭示了压缩工程里极重要的一点：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;换一个更强的熵编码器，收益可能只有几个百分点；让概率模型更懂数据，收益往往更大。&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;例如，一个编码器如果不知道“&lt;code&gt;q&lt;/code&gt; 后面很可能是 &lt;code&gt;u&lt;/code&gt;”，就只能按字母 &lt;code&gt;u&lt;/code&gt; 的全局频率编码；加入上下文后，它可以使用 $P(u\mid q)$，条件分布更偏斜，码长也更短。&lt;/p&gt;
&lt;h2 id=&#34;常见熵编码方法&#34;&gt;常见熵编码方法
&lt;/h2&gt;&lt;p&gt;&lt;a href=&#34;https://SymphonyW.github.io/p/entropy-coding-and-file-compression/entropy-coding-map.svg&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;img src=&#34;https://SymphonyW.github.io/p/entropy-coding-and-file-compression/entropy-coding-map.svg&#34; alt=&#34;常见熵编码方法的定位与取舍&#34; loading=&#34;lazy&#34; decoding=&#34;async&#34;&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;h3 id=&#34;huffman-coding给高频符号更短的前缀码&#34;&gt;Huffman Coding：给高频符号更短的前缀码
&lt;/h3&gt;&lt;p&gt;Huffman 编码反复合并概率最小的两个节点，最终得到一棵二叉树。左、右边分别记作 0、1，从根到叶子的路径就是符号码字。&lt;/p&gt;
&lt;p&gt;以前面的概率为例，可以得到：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;符号&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;概率&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;一组可行码字&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;码长&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;A&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;0.5&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;&lt;code&gt;0&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;B&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;0.25&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;&lt;code&gt;10&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;0.125&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;&lt;code&gt;110&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;D&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;0.125&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;&lt;code&gt;111&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;没有任何码字是另一个码字的前缀，所以解码器可以从左到右唯一解析。这个例子的平均码长恰好等于 1.75 bit/符号。&lt;/p&gt;
&lt;p&gt;Huffman 的优点是结构清楚、查表解码快、实现成熟；局限是&lt;strong&gt;每个符号的码长只能是整数个 bit&lt;/strong&gt;。当某符号概率是 0.9 时，理想码长只有约 0.152 bit，但普通二元 Huffman 仍至少要给它 1 bit。对单符号二元前缀码，平均码长满足 $H\le L&amp;amp;lt H+1$；把多个符号组成一块再编码可以摊薄这部分整数化损失，但码表也会迅速变大。&lt;/p&gt;
&lt;p&gt;Huffman 常见于 DEFLATE、PNG、基线 JPEG、Brotli 和 Zstandard 的部分符号流中。1952 年的 &lt;a class=&#34;link&#34; href=&#34;https://doi.org/10.1109/JRPROC.1952.273898&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Huffman 原始论文&lt;/a&gt; 给出了最小冗余前缀码的构造方法。&lt;/p&gt;
&lt;h3 id=&#34;arithmetic-coding把整个序列缩进一个概率区间&#34;&gt;Arithmetic Coding：把整个序列缩进一个概率区间
&lt;/h3&gt;&lt;p&gt;算术编码不急着给每个符号分配独立码字，而是维护一个区间 $[L,H)$：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;初始区间是 $[0,1)$；&lt;/li&gt;
&lt;li&gt;按当前概率把区间切成若干段；&lt;/li&gt;
&lt;li&gt;读到哪个符号，就选择它对应的子区间；&lt;/li&gt;
&lt;li&gt;对后续符号重复细分；&lt;/li&gt;
&lt;li&gt;最后选一个落在最终区间内的二进制小数作为编码结果。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;如果序列概率为 $P(x_1,x_2,\ldots,x_n)$，理想码长接近：&lt;/p&gt;
&lt;p&gt;$$
-\log_2 P(x_1,x_2,\ldots,x_n)
$$&lt;/p&gt;
&lt;p&gt;因为它对&lt;strong&gt;整段序列&lt;/strong&gt;分配比特，码长不必在每个符号边界上取整数，所以通常比逐符号 Huffman 更接近熵极限。实际实现需要处理有限精度、区间缩放、进位和终止标记；专利历史也曾影响它在部分格式中的普及。&lt;/p&gt;
&lt;p&gt;算术编码可以配合静态模型，也可以边编码边更新概率。真正决定效果的是“区间编码器 + 概率模型”的组合，而不是单独的区间操作。&lt;/p&gt;
&lt;h3 id=&#34;range-coding算术编码的工程化整数实现&#34;&gt;Range Coding：算术编码的工程化整数实现
&lt;/h3&gt;&lt;p&gt;Range Coding 通常被视为算术编码的一类实现。它不直接维护无限精度小数，而是使用固定宽度整数表示 &lt;code&gt;low&lt;/code&gt; 与 &lt;code&gt;range&lt;/code&gt;，区间过小时就输出高位并重新归一化。&lt;/p&gt;
&lt;p&gt;两者在思想上几乎相同：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;对比&lt;/th&gt;
&lt;th&gt;Arithmetic Coding&lt;/th&gt;
&lt;th&gt;Range Coding&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;核心对象&lt;/td&gt;
&lt;td&gt;概率区间&lt;/td&gt;
&lt;td&gt;整数范围&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;理论基础&lt;/td&gt;
&lt;td&gt;整段序列落入嵌套区间&lt;/td&gt;
&lt;td&gt;同一原理&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;工程重点&lt;/td&gt;
&lt;td&gt;精度、进位、重归一化&lt;/td&gt;
&lt;td&gt;整数乘除、字节输出、重归一化&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;常见印象&lt;/td&gt;
&lt;td&gt;教科书概念更常见&lt;/td&gt;
&lt;td&gt;压缩器实现中更常见&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;所以不应把 Range Coding 理解成与算术编码毫无关系的另一套理论；它更像同一思想的一种机器友好表达。LZMA 系列就会把 LZ 产生的符号交给 Range Coder。&lt;/p&gt;
&lt;h3 id=&#34;ans用一个整数状态吸收和释放符号&#34;&gt;ANS：用一个整数状态吸收和释放符号
&lt;/h3&gt;&lt;p&gt;ANS（Asymmetric Numeral Systems，非对称数字系统）维护一个整数状态。编码符号时，状态根据符号概率跳到新的状态，并在状态过大时输出低位；解码则根据当前状态恢复符号并回到前一个状态。&lt;/p&gt;
&lt;p&gt;常见变体包括：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;变体&lt;/th&gt;
&lt;th&gt;特点&lt;/th&gt;
&lt;th&gt;常见定位&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;rANS&lt;/td&gt;
&lt;td&gt;用整数算术更新状态&lt;/td&gt;
&lt;td&gt;软件实现、便于多路并行&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;tANS&lt;/td&gt;
&lt;td&gt;把状态转移预先放进表中&lt;/td&gt;
&lt;td&gt;查表快，需构建状态表&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FSE&lt;/td&gt;
&lt;td&gt;有限状态熵编码，属于 tANS 家族的工程实现&lt;/td&gt;
&lt;td&gt;Zstandard 的长度、距离等符号&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;ANS 能像算术编码一样利用细粒度概率，又可以通过状态机和查表获得很高吞吐，因此现代压缩格式经常使用它。Jarek Duda 的 &lt;a class=&#34;link&#34; href=&#34;https://arxiv.org/abs/1311.2540&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;ANS 论文&lt;/a&gt; 系统讨论了它在压缩率与速度之间的定位。&lt;/p&gt;
&lt;p&gt;ANS 也有自己的工程复杂度：频率必须归一化到有限状态数，表需要随码流保存或约定，典型编码与解码方向相反，多路交织时还要谨慎管理状态。因此“ANS 一定优于一切”并不成立，实际选择仍取决于数据规模、延迟、内存、硬件和实现质量。&lt;/p&gt;
&lt;h3 id=&#34;golomb--rice专门善待小整数残差&#34;&gt;Golomb / Rice：专门善待小整数残差
&lt;/h3&gt;&lt;p&gt;Golomb 编码适合近似几何分布的非负整数。给定参数 $m$，把整数 $n$ 写成：&lt;/p&gt;
&lt;p&gt;$$
n=qm+r
$$&lt;/p&gt;
&lt;p&gt;商 $q$ 使用一元码，余数 $r$ 使用截断二进制码。Rice 编码是 $m=2^k$ 的特例，因此商、余数可用移位和掩码快速得到。&lt;/p&gt;
&lt;p&gt;它特别适合“绝大部分残差接近 0，少数残差较大”的数据。带符号残差通常先映射成非负数，例如：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;0 → 0, -1 → 1, +1 → 2, -2 → 3, +2 → 4, ...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;FLAC 会先做线性预测，再用 Rice 类编码保存预测残差。这里真正制造可压缩性的主要是预测，Rice 负责把已经偏向小整数的残差高效写成比特。&lt;/p&gt;
&lt;h3 id=&#34;context--binary-arithmetic以-cabac-为代表的组合系统&#34;&gt;Context + Binary Arithmetic：以 CABAC 为代表的组合系统
&lt;/h3&gt;&lt;p&gt;CABAC 不是单一“神奇码表”，而是三部分的组合：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;二值化&lt;/strong&gt;：把多值语法元素拆成二进制决策；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;上下文建模&lt;/strong&gt;：根据邻近块、已编码语法等选择概率状态；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;二进制算术编码&lt;/strong&gt;：依据该概率输出比特流。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;它再次说明：实际系统往往把“模型”和“熵编码核心”紧密组合。讨论压缩率时，只说用了算术编码却不说概率如何得到，信息是不完整的。&lt;/p&gt;
&lt;p&gt;把这些方法放在一起看：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;方法&lt;/th&gt;
&lt;th&gt;基本单位&lt;/th&gt;
&lt;th&gt;优势&lt;/th&gt;
&lt;th&gt;代价或限制&lt;/th&gt;
&lt;th&gt;常见场景&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Huffman&lt;/td&gt;
&lt;td&gt;单个符号的前缀码&lt;/td&gt;
&lt;td&gt;简单、快速、成熟&lt;/td&gt;
&lt;td&gt;码长整数化&lt;/td&gt;
&lt;td&gt;DEFLATE、JPEG、PNG、Brotli&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Arithmetic&lt;/td&gt;
&lt;td&gt;整段序列的区间&lt;/td&gt;
&lt;td&gt;压缩率接近熵极限&lt;/td&gt;
&lt;td&gt;串行依赖与实现细节较多&lt;/td&gt;
&lt;td&gt;图像、视频、上下文模型&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Range&lt;/td&gt;
&lt;td&gt;整数范围&lt;/td&gt;
&lt;td&gt;便于工程实现&lt;/td&gt;
&lt;td&gt;乘除与重归一化仍有成本&lt;/td&gt;
&lt;td&gt;LZMA、通用压缩器&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;rANS / tANS&lt;/td&gt;
&lt;td&gt;整数状态或状态表&lt;/td&gt;
&lt;td&gt;高吞吐、概率精度高&lt;/td&gt;
&lt;td&gt;表与状态管理复杂&lt;/td&gt;
&lt;td&gt;Zstandard、现代图像编码&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Golomb / Rice&lt;/td&gt;
&lt;td&gt;非负小整数&lt;/td&gt;
&lt;td&gt;极简，特别适合残差&lt;/td&gt;
&lt;td&gt;只适合特定分布&lt;/td&gt;
&lt;td&gt;FLAC、预测残差&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CABAC 类组合&lt;/td&gt;
&lt;td&gt;上下文中的二进制决策&lt;/td&gt;
&lt;td&gt;能利用复杂局部条件&lt;/td&gt;
&lt;td&gt;计算与并行化成本高&lt;/td&gt;
&lt;td&gt;H.264/H.265 等视频编码&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;“静态还是自适应”是另一条独立维度。Huffman、Arithmetic、Range、ANS 都可以在不同程度上配静态频率表、分块更新或上下文模型，不能简单地把某一种编码器等同于某一种建模方式。&lt;/p&gt;
&lt;h2 id=&#34;常见文件压缩方法&#34;&gt;常见文件压缩方法
&lt;/h2&gt;&lt;p&gt;熵编码只压缩“符号概率不均匀”这一类冗余。完整文件压缩还会利用连续重复、重复子串、相邻相关、频域能量集中和人类感知不敏感等性质。&lt;/p&gt;
&lt;h3 id=&#34;rle把连续重复写成值--次数&#34;&gt;RLE：把连续重复写成“值 + 次数”
&lt;/h3&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;AAAAAAAABBBCC  →  (A,8)(B,3)(C,2)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;RLE（Run-Length Encoding）对掩码、空白区域、扫描线和量化后大量为零的系数非常有效，但对 &lt;code&gt;ABABABAB&lt;/code&gt; 无能为力，因为相同符号没有连续出现；对噪声数据还可能因计数信息而膨胀。&lt;/p&gt;
&lt;p&gt;RLE 不是狭义熵编码。它先把数据改写成“符号 + 游程长度”，之后仍可对符号和长度再做 Huffman、ANS 或 Rice 编码。&lt;/p&gt;
&lt;h3 id=&#34;lz77--lz78--lzw用引用代替重复内容&#34;&gt;LZ77 / LZ78 / LZW：用引用代替重复内容
&lt;/h3&gt;&lt;p&gt;Lempel-Ziv 家族利用重复字符串：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;LZ77&lt;/strong&gt; 在滑动窗口中向后查找匹配，用 &lt;code&gt;&amp;lt;距离, 长度&amp;gt;&lt;/code&gt; 代替重复片段；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LZ78&lt;/strong&gt; 显式构建短语字典，用字典索引表示新短语；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LZW&lt;/strong&gt; 在 LZ78 思路上让编解码器同步扩展字典，码流主要保存索引。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;例如：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;the_cat_and_the_cat
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            └─────┘  可以引用前面出现过的 &amp;#34;the_cat&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;LZ 方法利用的是&lt;strong&gt;重复子串&lt;/strong&gt;，不要求相邻数值接近。&lt;code&gt;ABCDEFGABCDEFG&lt;/code&gt; 数值并不平滑，但第二个 &lt;code&gt;ABCDEFG&lt;/code&gt; 仍可以被一次回引用压缩。&lt;/p&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://datatracker.ietf.org/doc/html/rfc1951&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;DEFLATE 规范 RFC 1951&lt;/a&gt; 明确规定每个块结合 LZ77 与 Huffman：LZ77 把输入变成字面量、长度和距离，Huffman 再编码这些符号。这正是“去重复 + 熵编码”的经典分工。&lt;/p&gt;
&lt;h3 id=&#34;bwt--mtf先把相似上下文聚到一起&#34;&gt;BWT + MTF：先把相似上下文聚到一起
&lt;/h3&gt;&lt;p&gt;BWT（Burrows-Wheeler Transform）是一种可逆重排。它不会直接缩短数据，却会让拥有相似后缀上下文的字符聚集，使输出更容易出现长游程。典型链路是：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;BWT → Move-to-Front → RLE → Huffman
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;bzip2 就采用这一类设计。BWT 的意义不是“字符本身发生了变化”，而是&lt;strong&gt;重新组织顺序，创造更强的局部性&lt;/strong&gt;，让后续 MTF、RLE 和熵编码更有效。&lt;/p&gt;
&lt;h3 id=&#34;delta-与预测编码不存原值存没猜中的部分&#34;&gt;Delta 与预测编码：不存原值，存“没猜中的部分”
&lt;/h3&gt;&lt;p&gt;对时间戳、传感器、音频、像素等连续信号，相邻值常常接近。Delta Coding 保存：&lt;/p&gt;
&lt;p&gt;$$
d_i=x_i-x_{i-1}
$$&lt;/p&gt;
&lt;p&gt;更一般的预测编码会先计算预测值 $\hat{x}_i$，再保存残差：&lt;/p&gt;
&lt;p&gt;$$
e_i=x_i-\hat{x}_i
$$&lt;/p&gt;
&lt;p&gt;只要预测准确，残差就会大量集中在 0 附近。PNG 为每条扫描线提供 None、Sub、Up、Average、Paeth 五类可逆过滤器，目的就是在 DEFLATE 前把像素字节转换成更适合压缩的残差；&lt;a class=&#34;link&#34; href=&#34;https://www.w3.org/TR/PNG-Filters.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;PNG 规范&lt;/a&gt; 也明确把过滤称为压缩前的准备步骤。&lt;/p&gt;
&lt;h3 id=&#34;变换编码把相关性搬到少数系数上&#34;&gt;变换编码：把相关性搬到少数系数上
&lt;/h3&gt;&lt;p&gt;DCT、小波、MDCT 等变换会把空间域或时间域信号转到频率域。自然图像的相邻像素通常接近，经过 DCT 后，能量常集中在少数低频系数，其余高频系数较小。&lt;/p&gt;
&lt;p&gt;变换本身可以完全可逆，也不必减小数据量；它的价值是改变表示方式。后续如果：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;无损保存所有系数，只是重新建模，仍属于无损压缩；&lt;/li&gt;
&lt;li&gt;对系数进行舍入、截断或分档，就进入有损压缩。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;量化真正丢信息的步骤&#34;&gt;量化：真正“丢信息”的步骤
&lt;/h3&gt;&lt;p&gt;量化把一段取值映射到同一个代表值。例如 JPEG 中：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;DCT 系数  3, -2, 1, 0  ──较粗量化──&amp;gt;  0, 0, 0, 0
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;大量小系数变成 0 后，游程编码和熵编码都更有效，但原值无法精确恢复。因此：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;JPEG 常见的失真主要来自色度抽样与量化，不来自 Huffman。Huffman 只是无损地编码量化后的符号。&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;原始 JPEG 标准同时定义过 Huffman 与算术熵编码；&lt;a class=&#34;link&#34; href=&#34;https://www.itu.int/en/ITU-T/studygroups/2009-2012/Pages/16/jpeg1x_about.aspx&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;ITU 对 JPEG-1 的说明&lt;/a&gt; 指出，基线流程要求 Huffman，而其他流程也可使用算术编码。&lt;/p&gt;
&lt;h3 id=&#34;专用模型懂数据结构通常比通吃压得更好&#34;&gt;专用模型：懂数据结构，通常比“通吃”压得更好
&lt;/h3&gt;&lt;p&gt;通用压缩器只看到字节；专用压缩器知道数据的含义：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;FLAC 知道输入是音频采样，可做声道去相关、线性预测和 Rice 残差编码；&lt;/li&gt;
&lt;li&gt;PNG 知道二维像素邻域，可按扫描线选择预测过滤器；&lt;/li&gt;
&lt;li&gt;JPEG 知道图像的颜色与频率结构，可做颜色变换、DCT 和量化；&lt;/li&gt;
&lt;li&gt;视频编码器知道帧间运动，可用运动补偿生成小残差；&lt;/li&gt;
&lt;li&gt;列式数据库知道一列具有同一类型，可选择 Delta、RLE、字典或位打包。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;代价是适用范围变窄、格式更复杂。没有一种方法在所有文件上都最优。&lt;/p&gt;
&lt;h2 id=&#34;常见格式究竟组合了什么&#34;&gt;常见格式究竟组合了什么
&lt;/h2&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;格式或算法&lt;/th&gt;
&lt;th&gt;前端去冗余 / 变换&lt;/th&gt;
&lt;th&gt;熵编码&lt;/th&gt;
&lt;th&gt;无损 / 有损&lt;/th&gt;
&lt;th&gt;备注&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;RLE&lt;/td&gt;
&lt;td&gt;连续游程&lt;/td&gt;
&lt;td&gt;可无独立熵编码&lt;/td&gt;
&lt;td&gt;无损&lt;/td&gt;
&lt;td&gt;数据不成段重复时可能变大&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LZW / GIF&lt;/td&gt;
&lt;td&gt;自增长字典&lt;/td&gt;
&lt;td&gt;固定或变宽索引码&lt;/td&gt;
&lt;td&gt;无损&lt;/td&gt;
&lt;td&gt;GIF 还受调色板限制&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;gzip / DEFLATE&lt;/td&gt;
&lt;td&gt;LZ77&lt;/td&gt;
&lt;td&gt;Huffman&lt;/td&gt;
&lt;td&gt;无损&lt;/td&gt;
&lt;td&gt;gzip 是封装，DEFLATE 是核心压缩格式&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ZIP&lt;/td&gt;
&lt;td&gt;取决于条目所选方法，常见为 DEFLATE&lt;/td&gt;
&lt;td&gt;取决于方法&lt;/td&gt;
&lt;td&gt;通常无损&lt;/td&gt;
&lt;td&gt;ZIP 更像可容纳多个文件与多种方法的归档容器&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PNG&lt;/td&gt;
&lt;td&gt;扫描线预测过滤&lt;/td&gt;
&lt;td&gt;DEFLATE 中的 Huffman&lt;/td&gt;
&lt;td&gt;无损&lt;/td&gt;
&lt;td&gt;还包含块结构与 CRC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;bzip2&lt;/td&gt;
&lt;td&gt;BWT + MTF + RLE&lt;/td&gt;
&lt;td&gt;Huffman&lt;/td&gt;
&lt;td&gt;无损&lt;/td&gt;
&lt;td&gt;压缩率较好，速度和随机访问一般&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;xz / LZMA2&lt;/td&gt;
&lt;td&gt;大窗口字典匹配&lt;/td&gt;
&lt;td&gt;Range Coding&lt;/td&gt;
&lt;td&gt;无损&lt;/td&gt;
&lt;td&gt;高压缩比通常伴随更多时间与内存&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Zstandard&lt;/td&gt;
&lt;td&gt;LZ77 类序列建模&lt;/td&gt;
&lt;td&gt;字面量用 Huffman，序列用 FSE&lt;/td&gt;
&lt;td&gt;无损&lt;/td&gt;
&lt;td&gt;兼顾速度、压缩率与可调级别&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Brotli&lt;/td&gt;
&lt;td&gt;LZ77 + 静态字典 + 上下文建模&lt;/td&gt;
&lt;td&gt;Huffman&lt;/td&gt;
&lt;td&gt;无损&lt;/td&gt;
&lt;td&gt;Web 文本资源常见；规范见 &lt;a class=&#34;link&#34; href=&#34;https://datatracker.ietf.org/doc/html/rfc7932&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;RFC 7932&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JPEG&lt;/td&gt;
&lt;td&gt;颜色变换 + DCT + 量化 + 游程&lt;/td&gt;
&lt;td&gt;常见为 Huffman&lt;/td&gt;
&lt;td&gt;通常有损&lt;/td&gt;
&lt;td&gt;也定义了无损过程，但日常 JPEG 多指有损 DCT 流程&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FLAC&lt;/td&gt;
&lt;td&gt;去相关 + 线性预测&lt;/td&gt;
&lt;td&gt;Rice 类编码&lt;/td&gt;
&lt;td&gt;无损&lt;/td&gt;
&lt;td&gt;针对 PCM 音频&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;H.264 / H.265&lt;/td&gt;
&lt;td&gt;帧内/帧间预测 + 变换 + 量化&lt;/td&gt;
&lt;td&gt;CAVLC / CABAC 等&lt;/td&gt;
&lt;td&gt;通常有损&lt;/td&gt;
&lt;td&gt;主要压缩收益来自预测和量化&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Zstandard 是很好的现代例子：&lt;a class=&#34;link&#34; href=&#34;https://datatracker.ietf.org/doc/html/rfc8878&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;RFC 8878&lt;/a&gt; 描述了它如何分别编码字面量与匹配序列，并使用 Huffman 与 FSE 两类熵编码。这说明一个格式内部甚至可以为不同符号流选择不同编码器。&lt;/p&gt;
&lt;h2 id=&#34;为什么局部连续性更有利于压缩&#34;&gt;为什么局部连续性更有利于压缩
&lt;/h2&gt;&lt;p&gt;“局部连续性好”通常表示相邻样本相同、相近，或能由邻域可靠预测。它真正带来的不是某种神秘加成，而是更低的&lt;strong&gt;条件不确定性&lt;/strong&gt;：&lt;/p&gt;
&lt;p&gt;$$
H(X_i\mid X_{i-1},X_{i-2},\ldots) &amp;lt; H(X_i)
$$&lt;/p&gt;
&lt;p&gt;知道附近数据后，下一个值更容易猜。预测器把这部分“已经能猜到的信息”剥离，只留下更集中的残差，熵编码器才有机会用更少的比特表示它。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://SymphonyW.github.io/p/entropy-coding-and-file-compression/locality-example.svg&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;img src=&#34;https://SymphonyW.github.io/p/entropy-coding-and-file-compression/locality-example.svg&#34; alt=&#34;相同直方图下，局部连续性如何改变差分残差&#34; loading=&#34;lazy&#34; decoding=&#34;async&#34;&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;看两段包含完全相同数字的序列：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;连续排列：100, 101, 102, 103, 104, 105, 106, 107
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;打乱排列：100, 107, 101, 106, 102, 105, 103, 104
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;它们的数值集合和出现次数完全一样，所以不考虑上下文的零阶经验熵都等于：&lt;/p&gt;
&lt;p&gt;$$
H_0=\log_2 8=3\ \text{bit/符号}
$$&lt;/p&gt;
&lt;p&gt;如果只按全局频率做静态 Huffman，两个序列的编码长度也一样，因为编码器根本不看顺序。&lt;/p&gt;
&lt;p&gt;做一阶差分后却完全不同：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;连续排列的差分：+1, +1, +1, +1, +1, +1, +1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;打乱排列的差分：+7, -6, +5, -4, +3, -2, +1
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;第一组残差几乎只有一个符号，第二组残差仍很分散。对大数据而言，前者可以用 RLE、Rice、Huffman、ANS 等极低成本编码；后者需要描述更多种残差。&lt;/p&gt;
&lt;p&gt;所以更准确的因果链是：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;局部连续 / 局部相关
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        ↓
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;邻域更能预测当前值
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        ↓
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;差值或预测残差集中在 0 附近
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        ↓
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;出现大量小值、零值和重复游程
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        ↓
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;概率分布更偏斜，条件熵更低
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        ↓
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;熵编码得到更短的平均码长
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这里必须强调一个边界：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;局部连续性通常不是直接帮助“无上下文熵编码器”，而是帮助预测器、变换、RLE、LZ 或上下文模型产生更容易熵编码的符号。&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;不同类型的“局部性”会喂饱不同算法：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;数据性质&lt;/th&gt;
&lt;th&gt;受益方法&lt;/th&gt;
&lt;th&gt;原因&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;相邻符号完全相同&lt;/td&gt;
&lt;td&gt;RLE&lt;/td&gt;
&lt;td&gt;直接形成长游程&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;相邻数值接近&lt;/td&gt;
&lt;td&gt;Delta、预测、Rice&lt;/td&gt;
&lt;td&gt;残差集中在 0 附近&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;一段字符串在附近重复&lt;/td&gt;
&lt;td&gt;LZ77&lt;/td&gt;
&lt;td&gt;回引用距离较短且仍在窗口内&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;相似上下文产生相似字符&lt;/td&gt;
&lt;td&gt;上下文模型、BWT&lt;/td&gt;
&lt;td&gt;条件概率更集中&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;相邻像素或采样高度相关&lt;/td&gt;
&lt;td&gt;DCT、小波、线性预测&lt;/td&gt;
&lt;td&gt;能量集中或残差变小&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;同类型记录聚在一起&lt;/td&gt;
&lt;td&gt;字典、RLE、Delta、位打包&lt;/td&gt;
&lt;td&gt;字段分布更稳定、重复更多&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;为什么二维图像尤其依赖扫描顺序&#34;&gt;为什么二维图像尤其依赖扫描顺序
&lt;/h3&gt;&lt;p&gt;图像是二维的，但最终文件是线性字节流。若按合理的扫描顺序保存，左右像素在流中相邻，上下像素也容易通过上一行缓冲区访问；如果把所有像素随机打乱，颜色直方图不变，空间结构却消失了。&lt;/p&gt;
&lt;p&gt;PNG 的 Sub、Up、Average、Paeth 过滤器正是在利用左、上、左上邻域。平滑天空中相邻像素原值可能是 &lt;code&gt;180, 181, 180, 182&lt;/code&gt;，过滤后变成 &lt;code&gt;180, 1, -1, 2&lt;/code&gt;；后面的小残差明显更集中。PNG 规范的设计说明指出，过滤能显著减小真彩色和灰度图像的压缩体积，原因就在这里。&lt;/p&gt;
&lt;h3 id=&#34;局部连续性不是越强越万能&#34;&gt;局部连续性不是越强越万能
&lt;/h3&gt;&lt;p&gt;还要注意几个反例：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ABCDEFGABCDEFG&lt;/code&gt; 不平滑，却有重复子串，LZ 会很喜欢；&lt;/li&gt;
&lt;li&gt;平滑递增序列的原始字节直方图可能很均匀，必须先做 Delta 或使用上下文才能获益；&lt;/li&gt;
&lt;li&gt;白噪声、加密数据和已经压缩过的数据通常缺少可利用结构，再压一次往往只增加文件头；&lt;/li&gt;
&lt;li&gt;局部相关范围超过字典窗口时，LZ77 可能看不到远处重复；&lt;/li&gt;
&lt;li&gt;为了制造局部性而排序记录，可能破坏原有顺序语义，还必须额外保存恢复顺序的信息；&lt;/li&gt;
&lt;li&gt;小文件即使数据可压缩，码表、文件头和校验和也可能抵消收益。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;怎样在工程中改善可压缩性&#34;&gt;怎样在工程中改善可压缩性
&lt;/h2&gt;&lt;p&gt;如果可以控制数据布局，通常先改善模型和局部性，再考虑更换熵编码器：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;数据类型&lt;/th&gt;
&lt;th&gt;常见做法&lt;/th&gt;
&lt;th&gt;产生的可压缩符号&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;单调时间戳&lt;/td&gt;
&lt;td&gt;Delta，必要时 Delta-of-Delta&lt;/td&gt;
&lt;td&gt;大量小整数或 0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;浮点传感器&lt;/td&gt;
&lt;td&gt;预测、XOR 相邻位模式、分块&lt;/td&gt;
&lt;td&gt;前导/尾随零与小残差&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;表格记录&lt;/td&gt;
&lt;td&gt;按列存储、同类聚簇、字典编码&lt;/td&gt;
&lt;td&gt;重复值、连续 ID、小索引&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RGB 图像&lt;/td&gt;
&lt;td&gt;颜色去相关、行过滤、分通道或分块&lt;/td&gt;
&lt;td&gt;小色差与局部残差&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;音频&lt;/td&gt;
&lt;td&gt;声道去相关、线性预测&lt;/td&gt;
&lt;td&gt;近零预测残差&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;文本&lt;/td&gt;
&lt;td&gt;词典、上下文建模、BWT 或 LZ&lt;/td&gt;
&lt;td&gt;短语引用与偏斜字符分布&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;稀疏张量&lt;/td&gt;
&lt;td&gt;索引差分、零游程、块稀疏&lt;/td&gt;
&lt;td&gt;小索引增量和长零段&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;实际优化时可以按下面的顺序排查：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;先确认可逆性要求&lt;/strong&gt;：是否允许量化或丢失精度；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;识别冗余类型&lt;/strong&gt;：连续游程、重复子串、数值相关还是感知冗余；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;选择合适表示&lt;/strong&gt;：预测、Delta、字典、变换、重排或分块；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;再选择概率模型和熵编码器&lt;/strong&gt;：Huffman、Range、ANS、Rice 等；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;把元数据算进总成本&lt;/strong&gt;：码表、字典、索引、块头和校验和都占空间；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;用真实数据衡量&lt;/strong&gt;：同时测压缩率、压缩速度、解压速度、内存和随机访问。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;只盯压缩率容易做出错误选择。日志传输可能优先低延迟，软件包分发可能优先解压速度，冷归档可以接受慢压缩，数据库则可能更看重按块随机访问和直接在压缩数据上执行查询。&lt;/p&gt;
&lt;h2 id=&#34;最后总结&#34;&gt;最后总结
&lt;/h2&gt;&lt;p&gt;可以用三句话记住全文：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;熵编码是概率到比特的映射，文件压缩是从原始文件到可恢复码流的完整系统。&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;RLE、LZ、预测、Delta、BWT、变换和量化负责暴露或制造偏斜分布，Huffman、Arithmetic、Range、ANS、Rice 负责把这种偏斜变成更短的比特流。&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;局部连续性降低的是“给定邻域后的不确定性”；只有通过预测、差分、上下文或重排利用它，才会真正转化为压缩收益。&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;下一次看到“某格式使用 Huffman，所以它的压缩原理就是 Huffman”时，可以追问四件事：它先对数据做了什么变换？产生了哪些符号？概率由谁估计？文件里还保存了哪些元数据？把这四层分开，绝大多数压缩格式都会清楚很多。&lt;/p&gt;
&lt;h2 id=&#34;参考资料&#34;&gt;参考资料
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;D. A. Huffman, &lt;a class=&#34;link&#34; href=&#34;https://doi.org/10.1109/JRPROC.1952.273898&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;A Method for the Construction of Minimum-Redundancy Codes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Jarek Duda, &lt;a class=&#34;link&#34; href=&#34;https://arxiv.org/abs/1311.2540&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Asymmetric Numeral Systems: entropy coding combining speed of Huffman coding with compression rate of arithmetic coding&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;IETF, &lt;a class=&#34;link&#34; href=&#34;https://datatracker.ietf.org/doc/html/rfc1951&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;RFC 1951: DEFLATE Compressed Data Format Specification&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;IETF, &lt;a class=&#34;link&#34; href=&#34;https://datatracker.ietf.org/doc/html/rfc7932&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;RFC 7932: Brotli Compressed Data Format&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;IETF, &lt;a class=&#34;link&#34; href=&#34;https://datatracker.ietf.org/doc/html/rfc8878&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;RFC 8878: Zstandard Compression&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;W3C, &lt;a class=&#34;link&#34; href=&#34;https://www.w3.org/TR/PNG-Filters.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;PNG Specification: Filter Algorithms&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;ITU-T, &lt;a class=&#34;link&#34; href=&#34;https://www.itu.int/en/ITU-T/studygroups/2009-2012/Pages/16/jpeg1x_about.aspx&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;JPEG-1 entropy coders overview&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        
    </channel>
</rss>
