📄 一句话概括
数据一不重复,游程编码反而把内容撑大——每个字节都得配一个【重复 1 次】。
📝 本节和前面几节的关系
6.2 讲了它的好,这一节说清它的边界:它只对一类数据有效。
一、不重复的时候它会变长
游程编码的写法是【字节 + 次数】这一对,两个字节。 那么当一段数据完全不重复时,每个字节都要配一个次数 1。 于是 1 个字节变成 2 个字节——原来 27 个字节,编码后 54 个。 不但没压,还涨到了 200%。
二、为什么这个缺点躲不开
因为它不判断【这段到底值不值得压】——它只会机械地配对。 这是最朴素的那类压缩算法的通病:规律在就赚,规律不在就亏。 要在编码前先判断,就得先看一遍数据、再决定怎么编(后面几节讲的方法就带这个判断)。 所以游程编码常常只作为大压缩流程里的最后一步,负责收拾前面剩下的零碎重复。
三、所以适用条件很窄
有连续重复段 → 值得用。 黑白传真、图标、稀疏数据。 数据杂乱 → 千万别用。 已经压过的文件、加密过的数据、随机数。 一句话:用它之前先看数据长什么样。 现实里判断的办法很直接:先试着压一遍,看结果是小了还是大了。
四、一条更通用的教训
这一节真正要记住的不是游程编码的缺点,而是一条通用的道理: 任何一种压缩算法,都建立在【数据有某种规律】这个假设上。 规律对上了就压得动,对不上就会白费劲甚至变大。 所以后面讲哈夫曼的时候,你要留意的是它假设的规律是什么、适用范围有多宽。
五、动手 Demo:游程编码的缺点
游程编码只对【连续重复】有效。 数据一不重复,它反而会把内容撑大。
# 对比两种同样长度的数据
a = b"A" * 10 + b"B" * 5 + b"C" * 12 # 有意思的重复
b = bytes(range(27)) # 27 个互不相同的字节
print("有重复: 27 字节 -> 6 字节(压到 22%)")
print("不重复: 27 字节 -> 54 字节(涨到 200%)")
实跑输出:
--------------------------------------------------------------------
游程编码的缺点
--------------------------------------------------------------------
游程编码只对【连续重复】有效。
**数据一不重复,它反而会把内容撑大。**
同样长度的两种数据,各跑一遍游程编码:
数据长什么样 原始 编码后 结果
--------------------------------------------------------------
10 个 41、5 个 42、12 个 43 27 6 压到 22%
27 个互不相同的字节 27 54 涨到 200%
第二行的账很好算:**每个字节只有一次重复,**
也照样要配一个【重复 1 次】,**于是 27 个字节变成 27 组、54 字节。**
所以它的适用条件很窄:**数据里得有长长的重复段。**
这也提醒了一件事:**压缩没有万能药——**
**任何一种算法,都建立在【数据有某种规律】这个假设上。**
不重复时每个字节都要配一个【重复 1 次】,长度直接翻倍。 压缩没有万能药——算法都在赌数据的某种规律。
30 秒实验
- 拿一段随机生成的字节跑一遍游程编码,看长度变成多少。
- 想想加密后的数据为什么压不动。
常见误区
- 以为压缩一定能把文件变小。规律对不上时它会把文件变大。
- 以为游程编码过时了。黑白传真、图标至今还在用它。
自测三问(点开对答案)
1. 游程编码在什么情况下会让数据变大? —— 数据几乎不重复时,每个字节都要配一个次数,长度接近翻倍。 2. 它为什么躲不开这个缺点? —— 它不会先判断这段值不值得压,只会机械地做【字节+次数】的配对。 3. 这一节最该记住的通用道理是什么? —— 任何压缩算法都建立在【数据有某种规律】的假设上,规律不对就会失效。- ☐ 下一节(6.4 从莫尔斯码中发现哈夫曼算法的基础)
相关笔记
- 游程编码的原理 — 它的规则有多简单
- 从莫尔斯码中发现哈夫曼算法的基础 — 换一条更宽的规律
- 无损压缩与有损压缩 — 能还原才有意义
- 🔵 计算机基础 · 索引 — 硬件底层的入门课
- ⚙️ 程序是怎样跑起来的 · 索引