使用方法
- 把文字粘进上面的文本框,或直接输入。打开页面时框里已经有一段 4 行示例,八张统计卡与下面的频率表显示的就是它的结果。
- 看第一排卡片区分口径:总码点是整段文本的字符个数(示例 118),字母总数只数 A–Z / a–z(示例 61),两者之差 57 就是非字母部分。
- 大写字母与小写字母分开计数(示例 11 与 50),用来检查一段文本的大小写是否符合规范,比目视扫一遍可靠得多。
- 元音与辅音默认按 a、e、i、o、u 五个元音划分,y 归辅音(示例 24 与 37)。需要按「y 也是元音」的口径统计时,勾上「把 y 计入元音」,元音立刻变成 25、辅音 36。
- 频率表逐行给出 a 到 z 每个字母的小写次数、大写次数、合计次数、占字母总数的百分比和它的类别。表里默认显示 12 行,往下拉会出现「加载更多」。
- 「只显示出现次数 ≥」用来压缩长表:填 1 保留全部 26 行,填 2 只剩 16 行,填 6 只剩 a、e 两行。数字框里按 Enter 应用,文本框里按 Ctrl + Enter 立刻重算。
- 「复制对照表」把整张频率表以制表符(TSV)复制到剪贴板,「导出 CSV」下载带 BOM 的表格文件,Excel 打开不乱码。
这个字母统计能解决什么问题
一是核对大小写规范。标题型文案里混进小写、变量名里混进大写,肉眼很容易漏掉。把整段粘进来,看「大写字母」是不是等于你预期的个数,比逐字检查快得多。
二是排查「看着像字母其实不是」的字符。从 Word、PDF、某些排版软件里复制出来的文本,经常混着全角 A(U+FF21)或带重音的 é(U+00E9)。它们在屏幕上和普通拉丁字母几乎一样,却不在 ASCII 区间里,程序按 a–z 处理时全部落空。这个字母统计只认 A–Z 与 a–z,把这类字符直接排除在字母之外,一眼就能看出「字母总数」是不是被低估了。
三是文本特征与用词分析。字母频率是最基础的文本指纹:英语里 e 和 a 通常排在最前,而示例这段 pangram 里 a 与 e 并列第一(各 6 次)。写密码学练习、做简单的文字游戏、比较两段文本的用词倾向,都会用到这张频率表。
四是验证码与编码类校验。字母统计只数 a–z,不掺汉字和符号,检查一串随机码里字母位数是否够、大小写比例是否失衡都很直接。
本页不做这些事:不统计汉字与标点(那要看总码点)、不做分词与词频排行、不做繁简转换、不检查拼写。要统计汉字个数请用页面底部的「文本统计工具」,要看某个词在文中占比请用「关键词密度检测」。
统计原理:逐码点遍历与 ASCII 区间分类
第一步是把文本逐个码点走一遍,写法是 [...x] 而不是 x.split('')。这不是风格问题:ECMAScript 的 String 类型内部用 UTF-16 存储,x.length 数的是 16 位码元,而 [...x] 走的是字符串迭代器(规范里 String 的 Symbol.iterator),每次吐出一个完整码点。遇到补充平面字符时两者结果不同:😀 是 U+1F600,在 UTF-16 里是一对代理 D83D DE00,算 2 个码元、1 个码点。示例文本按码点是 118,按码元是 119,差的正是那 1 个表情。
第二步是区间分类,判据只有两句比较:c >= 'A' && c <= 'Z' 算大写,c >= 'a' && c <= 'z' 算小写,其余一律不计入字母。对应到码位就是大写 U+0041–U+005A(十进制 65–90)与小写 U+0061–U+007A(十进制 97–122),两个区间各 26 个码位,且大小写之间恰好相差 32——也就是 'A'.charCodeAt(0) + 32 就是 'a'。这是 ASCII 沿用到 Unicode 的一条老规矩:把大小写合并统计时,只需要把大写码位加 32,不需要查表。
第三步是元音判定。默认元音集合固定为 a e i o u 五个字母,其余 21 个字母算辅音,5 + 21 = 26 正好覆盖整个字母表。这个划分来自英语传统教学口径,不是 Unicode 的定义——Unicode 只定义码位,不定义元音。争议点永远在 y:它在 gym、myth 里确实发元音,但在 yes、year 里是辅音,一个字母的归类取决于它在单词里的位置。本页默认把 y 归辅音,并额外给一个「把 y 计入元音」的开关,让你按自己那套口径复核——示例里切一下就差了 1 个元音(24 → 25)。
关键参数为什么这样取。「只显示出现次数 ≥」的下限是 1,因为计数为 0 的字母留在表里没有信息量;上限设 1000,是因为一段 20 万码点的文本里单个字母极难超过 1000 次,设得再高只会让用户误以为能过滤掉什么。文本上限 20 万字符是按 UTF-16 码元计的,超过之后输入框不再接收新内容——这是为了让「输入即统计」保持跟手,而不是为了限制篇幅。
完整示例(数值仅作演示)
示例条件就是页面打开时文本框里的那段文字:一行 26 字母 pangram、一行中文说明、一行含大写邮箱的英文,再加一个 emoji。全部指标实测如下:
- 总码点 118(按 UTF-16 码元是 119,多出来的 1 个码元来自那个
😀); - 字母总数 61,其中大写 11、小写 50;
- 元音 24、辅音 37,元音占全部字母的 39.3%,大写占 18.0%;
- 非字母 57 个,拆开是空白 17、汉字 31、其它符号 9、数字 0;
- 字母种数 26 / 26——那行 pangram 覆盖了全部 26 个字母,所以表里 26 行没有一行是 0;
- 出现最多的是
a与e,各 6 次,各占 9.84%;其次是o的 5 次(8.20%),再往下l、m、u各 4 次(6.56%)。
把 61 个字母按类别核对一遍,正好对上卡片上的数字:
| 类别 | 数量 | 拆解 |
|---|---|---|
| 元音 a | 6 | 小写 4 + 大写 2(大写来自 LIUQUAN 里的 A) |
| 元音 e | 6 | 小写 5 + 大写 1(大写来自 Email 的 E) |
| 元音 i | 3 | 小写 2 + 大写 1 |
| 元音 o | 5 | 全部小写 |
| 元音 u | 4 | 小写 2 + 大写 2 |
| 辅音合计 | 37 | 21 个辅音字母全部出现过,出现最多的是 l、m 各 4 次 |
| 合计 | 61 | 24 元音 + 37 辅音,与「字母总数」完全一致 |
输入范围与对照表
「只显示出现次数 ≥」这个阈值直接决定表格有多长,下面是同一段示例在各级阈值下保留的行数(实测):
| 阈值 | 保留行数 | 剩下的字母 |
|---|---|---|
| 1(默认) | 26 | 全部 a–z |
| 2 | 16 | 把只出现 1 次的 b、d、f、g、j、k、s、v、w、y 等 10 个字母筛掉 |
| 3 | 8 | 只剩 a、e、i、l、m、o、u、z,这 8 个字母都出现了 3 次以上 |
| 4 | 6 | 只剩 a、e、l、m、o、u |
| 5 | 3 | 只剩 a、e、o |
| 6 | 2 | 只剩 a、e |
| 7 及以上 | 0 | 示例里没有任何字母出现到 7 次,表格清空并给出提示 |
下面这些字符在屏幕上和普通字母几乎一样,但都不在 U+0041–U+005A 与 U+0061–U+007A 里,逐个列出来方便对照:
| 字符 | 码位 | 计入字母? | 码点/码元 | 说明 |
|---|---|---|---|---|
| a | U+0061 | 计入小写 | 1 / 1 | 小写区间的起点 |
| A | U+0041 | 计入大写 | 1 / 1 | 大写区间的起点,与小写相差 32 |
| É | U+00C9 | 不计入 | 1 / 1 | 预组合的重音大写 E,虽是大写字母但不是 ASCII |
| é | U+00E9 | 不计入 | 1 / 1 | 预组合的重音小写 e,欧洲语料里最常见的一类 |
| A | U+FF21 | 不计入 | 1 / 1 | 全角拉丁大写 A,中文输入法里很容易打出来 |
| a | U+FF41 | 不计入 | 1 / 1 | 全角拉丁小写 a,与半角 a 是两个不同码位 |
| а | U+0430 | 不计入 | 1 / 1 | 西里尔小写 a,字形与拉丁 a 完全相同 |
| α | U+03B1 | 不计入 | 1 / 1 | 希腊小写 alpha,理科文本里常见 |
| ß | U+00DF | 不计入 | 1 / 1 | 德语小写字母,语言上确实是字母,但不在 a–z 区间 |
| 𝐀 | U+1D400 | 不计入 | 1 / 2 | 数学粗体大写 A,位于补充平面 |
| 𝑎 | U+1D44E | 不计入 | 1 / 2 | 数学斜体小写 a,同样在补充平面 |
| 😀 | U+1F600 | 不计入 | 1 / 2 | emoji,1 个码点、2 个码元,正是两种口径的分歧点 |
结果边界与舍入说明
- 只认 ASCII 的 A–Z 与 a–z。重音拉丁字母、全角字母、希腊字母、西里尔字母、德语 ß 一律不计入字母,但会计入「总码点」。做国际化文本统计时,请把「字母总数」当成「ASCII 字母数」来理解。
- 组合重音字符会被拆成两半。用「e + U+0301 组合尖音符」输入的 é 是 2 个码点:前面的
e计入小写字母,后面的U+0301计入非字母;而预组合的é(U+00E9)是 1 个码点,两个都不计入。同样一个「é」,两种输入方式的统计结果不同,这不是 bug,而是 Unicode 归一化形式不同造成的。 - 百分比保留 2 位小数并四舍五入。示例里 26 项的百分比加起来是 100.04%,不是 100.00%——因为每项都独立四舍五入,误差会累积。需要严格校验时请用「合计」和「字母总数」两个整数比对,不要用百分比求和。
- 码点口径,不是码元口径。总码点走
[...x],emoji 与补充平面字符算 1 个;如果你需要按 UTF-16 码元(也就是x.length)统计,示例会从 118 变成 119。 - 阈值越高行数越少,但不会改变任何计数。阈值只控制表格显示多少行,卡片上的八项指标恒定按全文计算。
- 空文本与纯空白是两种不同的结果。文本框全空时八项指标都是 0、表格清空;只输入空格和换行时,总码点是空白个数、非字母等于总码点、字母总数为 0。
- 「字母种数」的分母固定是 26。它表示全文出现过几种不同字母(大小写合并后),所以示例显示 26 / 26;一段只有 hello 的文本会显示 4 / 26(h、e、l、o 四种)。
- 不做归一化。本页不执行 Unicode NFC/NFD 归一,也不做繁简或异体字转换,输入的每一个码点按原样分类。
常见问题
为什么「字母总数」比「总码点」少这么多?
因为总码点数的是整段文本的每一个码点,而字母总数只数落在 A–Z / a–z 里的那些。示例里 118 个码点中只有 61 个是字母,其余 57 个是空格、换行、汉字和标点。这个差值本身也有用——它等于「非字母」卡片上的数。
中文、日文里的假名会被算成字母吗?
不会。汉字(如「字」U+5B57)和日文假名都不在 ASCII 区间里,一律计入非字母。这个字母统计处理的是拉丁字母表,跨语言文本里它给出的「字母总数」实际含义是「ASCII 字母数」。
全角 A 和半角 A 会加在一起吗?
不会,而且只有半角 A 会被计入。全角 A 的码位是 U+FF21,半角是 U+0041,两者相差甚远。从中文输入法或某些排版软件复制英文时很容易带上全角字母,导致「字母总数」偏低,这时用「删除非 ASCII 字符」这类工具清洗一遍再统计会更准。
y 到底算元音还是辅音?
取决于判断口径,本页不替你做决定,只给一个开关。默认按英语教学的经典五元音 a e i o u 划分,y 归辅音;勾上「把 y 计入元音」后,示例里元音从 24 变成 25、辅音从 37 变成 36。字母 y 在 gym 里发元音、在 yes 里发辅音,同一个字母在不同单词里角色不同,所以两种口径都对。
为什么 26 个百分比加起来不是 100%?
因为每一行都独立保留 2 位小数,四舍五入的误差会累加。示例里 26 项之和实测是 100.04%,比 100 多出 0.04。要判断统计是否自洽,请核对整数:26 行的「合计」相加应等于「字母总数」61,这个等式是精确成立的。
emoji 在这里算几个字符?
按「总码点」算 1 个,因为它走的是 [...x] 码点迭代。同一个表情如果按 UTF-16 码元(x.length)会算成 2 个。示例里 118 与 119 的差额,就是那一个 emoji 造成的。两种算法都对,差别在于你把「一个字符」定义成码点还是码元。
空白字符和换行算不算进去?
算进「总码点」,不算进「字母」和「非字母」里的字母部分——它们计入「非字母」。示例里 57 个非字母中,空白占 17 个(含空格与换行)。想让它们不出现,可以先用「删除多余空格」或「删除空行」处理文本再粘进来。
最多能统计多长的文本?
上限 20 万字符,按 UTF-16 码元计(输入框的 maxlength)。超过之后输入框不再接收新内容,已在里面的文字不会被截断。文本接近上限时统计会有短暂延迟,按 Ctrl + Enter 可以立刻重算一次而不用等。