先把尺子本身量一遍
这篇要量的,是汉字转拼音页面背后那张拼音表:它有多大、对着一整份文本能命中多少、表外的字会怎么显示。量具不是随手敲的一段话,而是站内已经发布的简体全文 TXT:28903 字节、10211 个 UTF-16 码元、按码点数是 10209。码元比码点多 2,是因为文件里有且仅有 2 个增平面字——L219 一个 U+2C7FD、L788 一个 U+2AFA2,各占 2 个代理项码元。按 LF 切 819 段、818 个 LF、空段 148。这部书在本篇只当字符计量的尺子用,不引原文、不讲内容。
语料就是资源页 《笠翁对韵》 挂的那份 TXT。继续清点:汉字 7185、去重 2053;U+3000 全角空格 580、ASCII 空格 4;非汉字 3024。
表的规模,与「25 次」「21 字」两口径
词表在 public/static/js/pinyin-dict.js,实测 110567 字节;PINYIN_MAP 有 8026 键,POLYPHONES 有 72 键,72 个多音键同时全部在 8026 键里。被测页就是汉字转拼音,逐字取音走 getPinyin 查 PINYIN_MAP 那一步。
把 7185 个汉字逐字过一遍:命中 7160,落在 CJK_RE 范围内但表里没有值的有 25 次。命中率 7160 / 7185 = 99.65%;按去重口径是 2053 字里表内有值的 2032 个,98.98%。两个口径要分开:25 次按出现计,21 字按去重计。蕡、嘐、麌、毚 4 字各出现 2 次,嘐的两次还同在 L490——25 与 21 之间的差,正是这 4 字各多出来的那一次。
| 类别 | 字数 | 字头 | 判据落在哪 |
|---|---|---|---|
| A 只有繁体写法 | 2 | 對、韻 | 简体对应字都在表,取值 dui4、yun4 |
| B 简繁同形·本字表外 | 16 | 釭艭湡葅炤纑蝃蕡榼踘嘐薙麌毚睆瑊 | 繁简两侧查表都是空 |
| C 简体对应也表外 | 3 | 鱄、鳷、羵 | 对应简体本身落在增平面,如 U+2B68B |
图 1:汉字命中与 21 个表外字的分类账。
分类只认一条判据:这个字的简体对应字(按站内繁→简口径给出)是否也在 PINYIN_MAP 里。A 类的對、韻出现在 L815,是校勘、书目里出现的常用字异体写法,简体侧的对与韵都在表,所以不算未收录;B 类 16 字简繁同形,繁简两侧都查不到值;C 类 3 字的简体对应字本身就是增平面字,码点如 U+2B68B、U+2B6DB、U+2B157,同样落在表外。2 + 16 + 3 = 21,一条判据分干净三份账。
232 次多音字,只发一个音
多音字在这份语料里出现 232 次、涉及 42 个 POLYPHONES 键。但完整拼音、对照显示、首字母三档的输出全都取 PINYIN_MAP 的单一默认读音:行的 raw 值是 xing2,三档分别给 xíng、行(xíng)、x,而候选里挂着的 hang2 从不进任何一档的输出串。
候选只进结果下方那块 py-poly 面板——那段代码挂在 convert() 尾部、三档共用,与模式无关;整语料下面板恒 42 行,其中带顿号的 6 行是参、茸、切、得、差、佛,也就是除当前读音外还有 2 个以上候选的键。语料原文里的「、」标点共 2 个,与面板里那 6 个候选连接符是两本账,别混成一个数。
开关与档位的行为口径
首字母档取 py.charAt(0):zh、ch、sh 开头的音节 353、279、450 次只剩单字母 z、c、s,h 全部丢掉。元音起始的零声母字直接给元音本身,共 56 次;y 起始 727 次、w 起始 244 次。
声调开关不改输出长度:完整档、保留开、空格分隔下带调与不带调都是 32884 码元,无分隔都 25724——带调字符全是单码元,替换一码换一码。v→ü 那步是全串替换而不是只动标调位:语料含 v 的命中音节共 47 次,不带调档给恰好 47 个裸 ü;带调档 ǚ 32 加 ǜ 12 加 ǘ 2 得 46 个预组合带调字符,另 1 次标在 e 上、尾部替换把非标调位的 v 换成裸 ü 留在结果里,46 + 1 = 47。标调位按元音优先级落点、v 兜底,所以 nv4 写作 nǜ、lve4 写作 lüè;轻声以 0 尾的值表内 28 个,本语料命中 2 字,带调档也不给符号。
图 2:保留开关与分隔符的长度账,全按码元。
「保留非汉字」两态的输出长度差 3051 码元,账目是 3024 个非汉字、25 次表外汉字、2 个增平面字各多占的 1 个码元。表外字与增平面字的去留也挂在这一个开关上,关掉它连 818 个 LF 都一并吃掉。三种非空分隔各让整串加 7160 个字符:分隔符只跟在命中拼音之后,表外字与非汉字之后一个都不加,所以空格、连字符、下划线三档完全等长。
stat 四格与空输入的残留
整语料喂进去,full、compare、initial 三档的统计四格恒定:已注音 7160、未收录汉字 25、其他字符 3024、总字符 10211。末格取 input.length,是码元口径,比码点 10209 多 2,与开头那 2 个增平面字同根因——那两个字在 stat 里归进「其他字符」而非「未收录汉字」,因为 CJK_RE 只覆盖基本平面。
空输入时 convert 提前返回:输出与 stat 清空,但这一步在多音面板重建之前。先喂整语料、再清空输入框,页面上结果区空着,「多音字 42 个」的面板却还挂在原处。
常见问题
Q:25 次和 21 字,是同一件事吗?
不是。25 按出现次数计,21 按去重字头计,差额来自蕡、嘐、麌、毚各出现 2 次——25 次不等于 25 个字。
Q:整份文件转出来,表外字会被怎么处理?
默认开着「保留非汉字」时,25 次表外原样拼入输出、不进拼音括号;关掉它,表外汉字与非汉字一起消失,两态长度差 3051 码元。stat 的「未收录汉字」一格报的就是那 25。
Q:多音字候选要切到对照模式才看得到吗?
不是。py-poly 面板挂在三档共用的收尾段,与模式无关;但候选不参与选音,三档输出全取 PINYIN_MAP 的单一默认读音,需按语境人工确认。注音本身怎么加是旧文汉字加拼音注音的场景口径,本篇不复述。
Q:这份语料本身讲了什么?
不处理。它在本篇只按字符计量出现,是量拼音表的一把尺,内容层面不做解读。