先把尺子本身量一遍
這篇要量的,是漢字轉拼音頁面背後那張拼音表:它有多大、對著一整份文本能命中多少、表外的字會怎麼顯示。量具不是隨手敲的一段話,而是站內已經發布的簡體全文 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:這份語料本身講了什麼?
不處理。它在本篇只按字元計量出現,是量拼音表的一把尺,內容層面不做解讀。