2026-11-01 信息熵:我算了一段中文的「信息量」

《数学之美》讲信息熵那一节,我的概括是:一段消息的信息量等于它的不确定性,可以精确算出来。我一直觉得"信息量"是个虚词,直到把它算成数字。

一、书里的主张

香农给的定义很朴素:一件事发生的概率越小,它发生带来的信息量越大。

单个事件的信息量是 -log2(p)。整个分布的平均信息量就是熵:

H = - Σ p_i · log2(p_i)

底数取 2,单位是 bit——也就是"平均需要几个二进制位来表达"。

这句"需要几个位"是关键。它不是比喻,是字面意思:一个序列的熵,就是编码它的理论下界。

二、先把最小的零件验一下

单事件的信息量 -log2(p):

概率 0.5    信息量   1.00 bit
概率 0.25   信息量   2.00 bit
概率 0.125  信息量   3.00 bit
概率 0.1    信息量   3.32 bit
概率 0.01   信息量   6.64 bit
概率 0.001  信息量   9.97 bit

概率每减半,信息量加 1 bit。这条曲线很符合直觉:掷一次硬币 1 bit,猜中一个千分之一的事件能拿到近 10 bit。

这部分没什么意外,公式就长这样。

三、然后算真东西

我写了一段 277 字的中文,和一段 530 字符的英文,按字符统计频率:

中文段落:277 个字符,用到 159 种不同字符
  熵 H = 6.909 bit/字符   (理论上界 log2(159) = 7.313)

英文段落:530 个字符,用到 33 种不同字符
  熵 H = 4.187 bit/字符   (理论上界 log2(33) = 5.044)

两个数都落在 0 和 log2(种类数) 之间,符合公式。中文 6.909 很接近上界 7.313,说明这段中文里字符分布相当均匀——因为 159 种字符摊在 277 个位置上,每种平均不到 2 次。

这就是样本小带来的问题:字符种类被高估,熵也是高估的。 真拿一本书来统计,常见字会明显集中,熵会比这个低不少。这一点我得说清楚,不能拿 6.9 当"中文的熵"。

四、真正有意思的是这个对比

把熵和"实际存储开销"放一起看:

中文:UTF-8 存一个字符固定 3 字节 = 24 bit
      熵只有 6.909 bit/字符
      理论压缩空间 = 24 / 6.909 = 3.47 倍

英文:ASCII 存一个字符固定 8 bit
      熵只有 4.187 bit/字符
      理论压缩空间 = 8 / 4.187 = 1.91 倍

昨天那篇写字符编码,算出"中文"两个字在 UTF-8 里是 6 个字节,每个字节 8 bit,一个汉字固定 24 bit。当时的结论是"这是个映射表,没有对错"。

今天这个数给了另一面:24 bit 里,真正有用的平均只有 6.9 bit。 剩下的 17 个 bit 是固定长度编码的浪费。

压缩算法干的就是这件事——把那 17 bit 里可恢复的部分去掉。所以"UTF-8 不是压缩格式"这句话,现在有了具体的数字支撑。

五、熵为零是什么样

26 个字母各一次     26 字符  熵 4.700 bit
26 个 a           26 字符  熵 0.000 bit
真实中文          277 字符  熵 6.909 bit

"26 个 a"的熵是 0。它当然有 26 个字符、占 26 字节,但它一点信息量都没有——因为你能完全预测它,看到第一个 a 就知道后面全是什么。

这就是熵容易被误读的地方:它衡量的不是长度,是猜不猜得到。

一个 10 MB 的文件如果全是 0,熵是 0,压缩后可能只有几 KB。反过来,一段 100 字的随机乱码,熵接近 log2(字符集),几乎压不动。这就是"加密后的数据不能被压缩"的原因。

六、一个我必须承认的坑

中文 6.909 和 英文 4.187 这两个数,不能直接说"中文信息量比英文大"。

因为单位不一样:一个汉字大致相当于一个语素或半句话的分量,一个英文字母只是半个音节。2500 个常用汉字 vs 26 个字母,字符集完全不同,字符熵没有可比性。

要比的话得按"每句话"或者"每个词"来算,那是另一套统计(词的熵、二元组的条件熵)。

书里那种"一个汉字的信息量是 X bit"的说法,我现在的理解是:它有前提,前提是统计口径一致。 脱离口径单看数字,很容易得出错误结论。

七、我的判断

熵这个公式本身没什么可怀疑的,跑一遍就对上了。真正有价值的是它给了一个「下界」的思路:

  • 存储的实际开销 vs 熵,差值就是可压缩的空间
  • 熵越低的序列越可预测,也就是越好压
  • 完全不可预测(随机)的序列,压不动

这三点解释了压缩软件、加密数据、以及"为什么日志能压得很小"。

至于"信息量"这个词,我现在能接受它了——它不是文艺说法,是"平均需要多少 bit 来表达"的另一种讲法。

附:核心代码

import math
from collections import Counter

def entropy(text):
    n = len(text)
    counts = Counter(text)
    h = 0.0
    for c, k in counts.items():
        p = k / n
        h -= p * math.log2(p)
    return h, len(counts), n

h, alpha, n = entropy("一段中文……")
print(f"{n} 个字符,{alpha} 种,熵 {h:.3f} bit/字符,上界 {math.log2(alpha):.3f}")
posted @ 2026-11-01 16:17  呱哒  阅读(19)  评论(0)    收藏  举报