字母统计

粘贴一段文本,逐码点分类计数:大写多少个、小写多少个、元音与辅音各多少,再给出 a 到 z 每个字母的出现次数与占比。

元音口径
总码点118
字母总数61
大写字母11
小写字母50
元音字母24
辅音字母37
非字母57
字母种数26 / 26
字母小写大写合计占字母%类别
a4269.84%元音
b1011.64%辅音
c2023.28%辅音
d1011.64%辅音
e5169.84%元音
f1011.64%辅音
g1011.64%辅音
h2023.28%辅音
i2134.92%元音
j1011.64%辅音
k1011.64%辅音
l3146.56%辅音

提示:统计随输入自动完成,不需要点按钮;文本框里按 Ctrl + Enter(macOS 用 Cmd + Enter)可以立刻重算一次。数字框里按 Enter 可直接应用新的显示阈值。

使用方法

  1. 把文字粘进上面的文本框,或直接输入。打开页面时框里已经有一段 4 行示例,八张统计卡与下面的频率表显示的就是它的结果。
  2. 看第一排卡片区分口径:总码点是整段文本的字符个数(示例 118),字母总数只数 A–Z / a–z(示例 61),两者之差 57 就是非字母部分。
  3. 大写字母与小写字母分开计数(示例 11 与 50),用来检查一段文本的大小写是否符合规范,比目视扫一遍可靠得多。
  4. 元音与辅音默认按 a、e、i、o、u 五个元音划分,y 归辅音(示例 24 与 37)。需要按「y 也是元音」的口径统计时,勾上「把 y 计入元音」,元音立刻变成 25、辅音 36。
  5. 频率表逐行给出 a 到 z 每个字母的小写次数、大写次数、合计次数、占字母总数的百分比和它的类别。表里默认显示 12 行,往下拉会出现「加载更多」。
  6. 「只显示出现次数 ≥」用来压缩长表:填 1 保留全部 26 行,填 2 只剩 16 行,填 6 只剩 a、e 两行。数字框里按 Enter 应用,文本框里按 Ctrl + Enter 立刻重算。
  7. 「复制对照表」把整张频率表以制表符(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。全部指标实测如下:

把 61 个字母按类别核对一遍,正好对上卡片上的数字:

类别数量拆解
元音 a6小写 4 + 大写 2(大写来自 LIUQUAN 里的 A)
元音 e6小写 5 + 大写 1(大写来自 Email 的 E)
元音 i3小写 2 + 大写 1
元音 o5全部小写
元音 u4小写 2 + 大写 2
辅音合计3721 个辅音字母全部出现过,出现最多的是 l、m 各 4 次
合计6124 元音 + 37 辅音,与「字母总数」完全一致

输入范围与对照表

「只显示出现次数 ≥」这个阈值直接决定表格有多长,下面是同一段示例在各级阈值下保留的行数(实测):

阈值保留行数剩下的字母
1(默认)26全部 a–z
216把只出现 1 次的 b、d、f、g、j、k、s、v、w、y 等 10 个字母筛掉
38只剩 a、e、i、l、m、o、u、z,这 8 个字母都出现了 3 次以上
46只剩 a、e、l、m、o、u
53只剩 a、e、o
62只剩 a、e
7 及以上0示例里没有任何字母出现到 7 次,表格清空并给出提示

下面这些字符在屏幕上和普通字母几乎一样,但都不在 U+0041–U+005A 与 U+0061–U+007A 里,逐个列出来方便对照:

字符码位计入字母?码点/码元说明
aU+0061计入小写1 / 1小写区间的起点
AU+0041计入大写1 / 1大写区间的起点,与小写相差 32
ÉU+00C9不计入1 / 1预组合的重音大写 E,虽是大写字母但不是 ASCII
éU+00E9不计入1 / 1预组合的重音小写 e,欧洲语料里最常见的一类
AU+FF21不计入1 / 1全角拉丁大写 A,中文输入法里很容易打出来
aU+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 / 2emoji,1 个码点、2 个码元,正是两种口径的分歧点

结果边界与舍入说明

常见问题

为什么「字母总数」比「总码点」少这么多?

因为总码点数的是整段文本的每一个码点,而字母总数只数落在 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 可以立刻重算一次而不用等。

相关工具