无损是把重复的规律记账省下来,账还在、随时能还原;有损是把看不出来的部分真的扔掉,账撕了、回不来。
6.6 把无损压缩压到了极限,这一节说清两类压缩的分界,也是本章的收口。
一、无损:账还在
无损压缩的做法是找出数据里的重复与规律,用更紧凑的方式记账。 记账并没有丢信息——所以随时能照账还原,一个字节都不差。 实测:27 个字节的数据压到 6 个,再解回来,与原文完全一致。 无损的典型场合:文本、程序、压缩包、数据库备份——这些东西差一个字节都可能出大事。
二、有损:账撕了
有损压缩干脆把一部分信息真的丢掉——赌的是【这点差别没人看得出来】。 实测:把每个字节的低 3 位丢掉(模拟量化),1024 个字节里有 896 个被改动(87.5%),最大误差 7。 因为是扔而不是记账,所以不可能还原。 换来的好处也很明确:压缩比比无损大得多,几十倍、上百倍都有可能。
三、各自靠什么、用在哪
无损靠规律:重复、频率、上下文——凡是数据里有规律的地方都能下手。 有损靠感知:人眼对亮度敏感对色度迟钝、人耳对某些频率不敏感——专挑感知不到的地方扔。 无损用在哪:文本、程序、代码、压缩包、医疗影像、法律文档。 有损用在哪:图片、音频、视频——只要最终是给人看的,就有商量的余地。
四、怎么选,一句话
问自己一个问题:这份数据将来要不要被精确还原? 要——只能用无损,压不动也得认。 不要——优先有损,能省的空间大得多。 所以同一个系统里两类常常并存:日志和配置用无损,封面图和视频用有损。 这也回过头点亮了整章的主线:压缩不是魔法,只是把数据里的规律换成更短的写法。
五、动手 Demo:无损压缩与有损压缩
无损是记账省下的,随时能还原;有损是真的把看不出来的部分扔掉。 拿数据实测一遍就明白了。
src = b"A" * 10 + b"B" * 5 + b"C" * 12
enc = b"".join(bytes([v, k]) for v, k in
((0x41, 10), (0x42, 5), (0x43, 12)))
back = b"".join(bytes([enc[i]]) * enc[i + 1]
for i in range(0, len(enc), 2))
print("无损还原一致吗:", back == src)
raw = bytes(range(256)) * 4
lossy = bytes(x & 0xF8 for x in raw)
print("有损改动了", sum(1 for a, b in zip(raw, lossy) if a != b), "个字节")
实跑输出:
--------------------------------------------------------------------
无损压缩与有损压缩
--------------------------------------------------------------------
对比项 无损压缩 有损压缩
-----------------------------------------------------------------
能不能原样还原 能,一个字节都不差 不能,只能差不多
压缩比 通常两到五倍 可以到几十上百倍
靠什么 找数据里的重复与规律 丢掉人感觉不到的部分
典型场合 文本、程序、压缩包 图片、音频、视频
拿数据实测一遍。先看无损:
原始 27 字节
压缩后 6 字节
还原回来 完全一致
再看有损——**把每个字节的低 3 位直接丢掉**(模拟量化):
原始字节数 1024
被改动的字节 896(87.5%)
最大误差 7(低 3 位最大就是 7)
能原样还原吗 不能——信息已经真丢了
一句话分清两者:
**无损压缩是把【重复的规律】记账省下来,账还在,随时能还原。**
**有损压缩是把【看不出来的部分】真的扔掉,账撕了,再也回不来。**
无损往返上完全一致;有损改动后1024 个字节中 896 个变了(87.5%)、最大误差 7。 无损的账还在,有损的账撕了——这就是两类压缩的分界线。
30 秒实验
- 把一张 jpg 图片反复保存几十次,看画质会不会越来越差,为什么。
- 想想 zip 和 mp4 分别属于哪一类,能不能把 mp4 再无损压一半。
常见误区
- 以为无损压缩只是【质量更好】。它是能精确还原,不是好一点。
- 以为有损可以反复压缩。每压一次就丢一层,越压越糊。
自测三问(点开对答案)
1. 无损和有损的分界线是什么? —— 能不能一个字节都不差地还原——无损能,有损不能。 2. 两类压缩各自靠什么? —— 无损靠数据里的重复与规律;有损靠人的感知盲区,丢掉感觉不到的部分。 3. 怎么决定该用哪一类? —— 问这份数据将来要不要被精确还原:要就只能无损,不要就优先有损。- ☐ 下一章(第七章 程序在怎样的环境下运行)
相关笔记
- 通过哈夫曼算法大幅提高压缩效率 — 无损压缩的极限在哪
- 游程编码的原理 — 回头看最简单的那个例子
- 将内存当成磁盘使用的固态硬盘 — 省下来的空间确实有用
- 🔵 计算机基础 · 索引 — 硬件底层的入门课
- ⚙️ 程序是怎样跑起来的 · 索引