二维码为什么中文比英文占地方?

同样是几十个字,中文二维码看起来密密麻麻,英文的却疏朗很多。这不是错觉,是编码规则决定的。

做二维码的时候常遇到一个困惑:明明内容不多,生成的码已经密得看不清了;而别人的二维码扫的是个挺长的网址,看起来却稀疏得多。

原因在于二维码(QR Code)内部有四种不同的编码模式,不同字符走的通道不一样,占用的空间能差好几倍。理解这一点,你就能主动控制二维码的密度。

四种编码模式:同一条信息,大小差很多

QR 码为不同类型的字符准备了专门的编码方式,每种方式的「打包效率」不同:

模式 适用字符 每个字符占位 相对效率
数字模式0-9约 3.33 比特最高(省 40%)
字母数字模式0-9 A-Z 空格 $%*+-./:约 5.5 比特较高
字节模式其他所有字符(含中文)8 比特基准
汉字模式Shift-JIS 汉字13 比特对中日常用字略优

关键在于:一个汉字在 UTF-8 编码下占 3 个字节,也就是 24 比特。而一个英文字母只占 1 个字节(8 比特)。所以同样「20 个字」,中文要 480 比特,英文只要 160 比特——差 3 倍。

这就是中文二维码更密的最直接原因。

汉字模式能救一点,但有条件

QR 标准里有个专门的「汉字模式」,每个汉字只用 13 比特,比字节模式的 24 比特省将近一半。听起来很棒,但它有个硬性限制:只支持 Shift-JIS 编码里存在的汉字。

Shift-JIS 是日文编码,收录的汉字集合和 GB2312 或 Unicode 并不完全重合。所以:

实际使用中,很多生成器为了保证兼容性和正确性,干脆统一用字节模式。结果就是中文内容全部按 24 比特/字计算,二维码自然偏密。

顺便说个实用技巧:中文标点也是 3 字节。句号「。」、逗号「,」、顿号「、」都是全角字符,同样占 3 字节。如果内容里标点很多,可以改用半角标点试试,能省一些空间。

纠错等级:冗余换来的容错

二维码另一个吃空间的地方是纠错码。它用里德-所罗门算法给数据加了冗余,使得即使图案被污损一部分,仍然能还原出原始内容。四个等级:

冗余是实打实占地方的。同样是版本 10(57×57 格),L 级能存 271 字节,H 级只能存 119 字节——少了将近 56%。

所以如果你的二维码只需要印在屏幕上扫,用 L 或 M 就够了,图案会明显稀疏一些、更好扫。只有在二维码要印在可能磨损的实物上、或者中间要放 logo 时,才值得用 Q 或 H 级。

中间放 logo 的原理正是如此:logo 遮住的区域被当作损坏,靠 H 级那 30% 的冗余补回来。如果用 L 级再放 logo,基本就扫不出来了。

版本:二维码的「尺寸档位」

QR 码一共 40 个版本,版本 n 的边长是 4n + 17 个格点:

容量从版本 1 的几十字节,一路涨到版本 40 的 2953 字节(L 级、字节模式)。生成器会根据你的内容长度自动选最小的够用版本。

这里有两点值得注意:

实用结论:让二维码更好扫

想让二维码又清楚又好扫,按这个优先级优化:

怎么知道自己的二维码有多密

两个办法:

一是生成的时候看工具给出的版本号——版本越低越好扫。如果用二维码生成器,它会显示当前内容占用的版本和字节数,你可以边改内容边看版本变化,直观感受「删掉几个字能降一个版本」。

二是拿现成的二维码去二维码解码看看它的版本、纠错等级和内容类型。如果你看到一个号称很长的内容却是低版本的二维码,多半是内容里有短链接。

两个工具都在浏览器本地运行,生成的图片、上传的图片都不经过服务器。

一句话总结

二维码的密度 = 内容字节数 ÷ 编码效率 + 纠错冗余。 中文按 3 字节算、标点也按 3 字节算,所以中文码天然更密;想变稀疏,最有效的办法是减内容和降纠错等级,而不是换生成工具。

相关工具