「 」这个字符在百度中相当于「浏览器」三个字,这是为什么?

字符在手机端无法显示,看图片 [图片]
关注者
269
被浏览
318,898

13 个回答

你输入的三个字符分别是:

https://www.zdic.net/hans/%F0%A6%B5%8F
https://www.zdic.net/hans/%F0%A8%A7%88
https://www.zdic.net/hans/%F0%A5%99%A8

它们都不属于常用汉字所在的 Unicode 0 号平面(BMP),而是在 2 号辅助平面,这个平面里放的都是不常用的中日韩汉字,有几万个,所以常见字体不包含它们,所以只能用图片的形式展示它的字形。

这三个字组成字符串用 JavaScript 的 Unicode 转义形式表示是 \u{26D4F}\u{289C8}\u{25668},而百度的服务器在拿到这三个字后(经过浏览器 UTF8 百分号编码和服务器解码),不知有意还是无意,把码点里表示平面序号的 2 去掉,从而转换成了 BMP 里的常见汉字,也就是 \u{6D4F}\u{89C8}\u{5668},这三个字刚好就是“浏览器”

试验一下,看看 zhihu 能不能显示出来……

很遗憾,这里无法显示出来。


本来也想从编码上考虑的,不过 紫云飞 的回答已经说明了可能原因,我也不清楚服务器那边的情况,就不重复了。

不过,既然来了,不研究一下有点浪费时间。顺着这个思路再进行验证:

随便选一个U+2xxxx汉字,就会被 baidu 转换成U+xxxx?

按照上述假设,以下转换可能成立:

实际测试:

再来个转换:

结果也是可行的:


从 Unicode 的汉字区块范围来考虑:

常用的 中日韩统一表意文字 / CJK 位于 BMP(4E00~9FFF)

中日韩统一表意文字扩展B区 / CJK ExtB 位于 SIP(20000~2A6DF):

由于二者不是完全一 一对应(ExtB的汉字比常用的字数多),因此按照 baidu 的转换规则,可能存在以下的问题:

在CJK区块之前的一个字符(U+4DFF):

测试结果是不支持:


用常见的字符再测试一下CJK汉字以外的情况:

结果可以替换 英文字母:


看评论中提到的强制读取低16-bit,看来是比较可能的原因了。实际情况还比较复杂(可能和系统支持的字符有关),这里就不多测试了,有兴趣的话可以自己试验一下。


============================


王絮飞 建议要从历史的角度来看问题。

于是,又到了翻故纸堆的时刻。

上世纪80年代,ISO 成立了 ISO/IEC JTC1/SC2/WG2,对 ISO 646 标准进行升级——制定 ISO 10646,定义通用字符集(UCS, Universal Coded Character Set),用来包含已知语言的所有字符。

最初想使用16位来对UCS进行编码,据说因为无法兼容当时中国的汉字编码,因此扩充到了32位。

该工作组(ISO/IEC JTC1/SC2/WG2)现在仍然在运行之中:

(注意下图墙上的横幅文字)

2019年 全国科技名词委 派员参加 ISO/IEC JTC1/SC2/WG2/IRG 第53次会议 图片来自 www.cnctst.cn


1987年,施乐公司的 Joe Becker 与苹果公司的 Mark Davis 以及 Lee Collins 合作,启动了 Unicode 项目。三个程序员,顶个ISO……还不行。在那个386电脑都是高科技产品的年代,这几个人认为人们使用的文字之中,不同字符的数量不会超过 16384个( 2^{14} ),因此用16位进行编码,就完全足够了!结果 Unicode 就按16位编下去了。

Lee Collins (wikipedia.org)

16位 Unicode 的由来:


1991年,施乐和苹果等厂商觉得这个项目不错,就成立了 Unicode 联盟(The Unicode Consortium),继续对各种文字编码进行统一工作,进而形成标准。(有能力和 ISO 一起坐下来喝咖啡谈业务了)

后来 ISO 和 Unicode 发现双方在做着差不多的工作,于是在1991年决定互相兼容。也有说法是当时ISO想偷懒,把各国的汉字编码直接搬过来用,但遭到了反对。因为有 Unicode 这样一个好榜样,所以一些国家就建议 ISO 虚心学习,把各国的文字编码都仔细整理一下。因此,ISO 和 Unicode 共同成立了CJK-JRG,也就是后来的 IRG(The Ideographic Research Group),专门针对汉字编码问题进行研讨 ——上文照片即中国专家参加2019年 IRG 会议。


1992年,Unicode 1.0.1 加入了 CJK 字符(20902个,U+4E00~U+9FA5)—— 王絮飞 的回答中提到 第1版不支持中文,(大约8个月之后)Unicode 升级成 1.0.1版 补上了汉字。


1993年,ISO/IEC 10646.1-1993 标准发布。同年6月,Unicode 1.1 发布,与 ISO标准相对应。

该ISO标准中规定了 UCS 的总体结构、以及 UCS 的肆八位(32位)正则形式 UCS-4 和 UCS 的双八位(16位)BMP形式 UCS-2。

GB 13000.1-93 中的 UCS 总体结构 (等同采用 ISO/IEC 10646.1-1993)
GB 13000.1-93 中的 字符编码 (等同采用 ISO/IEC 10646.1-1993)

按照该规定,UCS的整个编码空间可达 2,147,483,648 个字符(0~0x7FFF FFFF),实际使用数量可能在 679,477,248 个左右(0~0x2880 0000)。

在上世纪末的一些 RFC 文件中也可以看到这个UCS-4的范围(0~0x7FFF FFFF)。

RFC 2044 (1996)
RFC 2279 (1998)

把上限 0x7FFF FFFF 从16进制换算为2进制:

显然,最高位0不计的话,实际使用31位。

用图形来表示 UCS 的编码空间:

从上图可以看到 组 的数量为 128个(Group 00~7F)。空间一共包含 32768 个(0~0x7FFF)平面,每个平面能容纳 65536 个(0~0xFFFF)字符。

当年数量庞大的 非BMP平面 有着长远的发展规划

3万多个平面,数以亿计的字符码位!(如果想起了上文 ISO 直接照搬各个国家编码 的说法,这3万个平面的用途就显而易见了。)ISO 果然高瞻远瞩——可得广厦亿万间!不过,电脑厂商们要考虑实际情况。就在这个标准发布的1993年,Pentium 66MHz CPU 刚问世。Windows 3.1 还是16位!方正和金山、联想、巨人仍在卖汉卡……ISO 想给UCS造那么多的楼,建那么多房间,可是造楼成本太高,入住率又太低。于是一帮开发商最终让128组缩水到1组都不满,3万多个平面改成了十几个——ISO只好降低了标准。

(史玉柱)巨人公司生产的 M6401汉卡


从 Unicode 13 的介绍来看,2020年收集的字符还不到15万个。ISO在1993年就给出上亿字符的空间,步子确实太大了!


1996年7月,Unicode 2.0 发布。ISO/IEC 10646.1-1993 标准也进行了修订。

慢慢地,UCS 的空间上限就变成了 0x10 FFFF

原先的 Group 00,有256个平面(Plane 00~FF)。包括1个基本多文种平面(BMP,Plane 00)、223个辅助平面(Plane 01~DF),以及 32个专用平面(Plane E0~FF) 。

上限降到 0x10 FFFF 之后,就只有17个平面了(0~0x10)。包括1个基本多文种平面(BMP,Plane 00)、16个辅助平面(Plane 01~10),每个平面容纳 65536 个(0~0xFFFF)字符。

精简之后的编码空间理论上可容纳 1,114,112 个字符(0~0x10 FFFF)。

RFC文件中同样可以看到这个变化:

RFC 3629 (2003)

再把上限 0x10 FFFF 从16进制改为2进制:

显然,只用了 21位——之前 王絮飞 的答案中也提到 好像是实际只需要21位



好累!写得有点多了。考古工作暂时告一段落,后续 UTF-8 等内容,下次再提吧……