使用方法
- 在「要拼写的数字」里填 1234(示例值),或者任意 −9007199254740991 到 9007199254740991 之间的数。填好后按 Enter,结果区立刻给出
one thousand two hundred and thirty-four。 - 「英式 and」默认勾选。勾着的时候 101 读作
one hundred and one;取消勾选走美式写法,读作one hundred one。 - 「21~99 加连字符」也默认勾选。它只影响 21 到 99 之间不是整十的那些数:勾着是
twenty-one,取消勾选变成twenty one。 - 需要整句首字母大写(放进标题或信函)时勾上「每个单词首字母大写」,数字转英文单词的输出会变成
One Thousand Two Hundred And Thirty-Four。 - 点「复制结果」把整串单词带走;点「载入示例 1234」随时回到默认值;下方对照表可以「加载更多」「复制对照表」或「导出 CSV」。
这个数字转英文单词能解决什么问题
一是填英文票据和合同。国际贸易用的汇票、信用证、英文合同里,金额栏旁边必须再写一遍英文单词,而且写法要跟着英式或美式的习惯走。输入 1234 得到 one thousand two hundred and thirty-four,抄写时不用担心漏掉那个 and。
二是给金额做交叉核对。财务单据上阿拉伯数字和英文单词是两套独立书写,任何一套写错都是事故。把数字丢进数字转英文单词、把英文单词逐词读回来对照,比人工重新数一遍位数可靠得多。
三是做朗读稿和语音字幕。口播稿里写 1234,配音演员可能念成「一千二百三十四」也可能念成「一二三四」;先拼成英文单词再交稿,读音就不会有歧义。英语里 thirteen 与 thirty 的重音位置不同,拼写出来也便于标注。
四是写测试数据和 i18n 词条。做多语言界面时经常需要「数字→单词」的对照样例,用它批量生成比手敲快,而且拿到的写法有一致的连字符规则。
本页不做这些事:不做序数词(first / twenty-first),不做 one half / two thirds 这类分数读法,不加货币单位(dollars、cents),也不做中文数字与人民币大写。要中文大写请用页面底部的「人民币大写转换」,要把「一千二百三十四」这类中文写法还原成阿拉伯数字请用「中文数字转阿拉伯数字」。
转换原理:短级差命名、三张查表与 and 的插入位置
核心是一个自己写的 intWords() 函数,按三位一组切分再查表。不要指望 Intl.NumberFormat:它是用来做数字本地化排版的(千分位、货币符号、百分号),并不提供「拼成英文单词」的能力,全站也没有任何原生 API 能把 1234 变成 one thousand two hundred and thirty-four。
三张表决定了全部拼写。第一张是个位与十几:zero 到 nineteen,共 20 项;第二张是整十:twenty 到 ninety,中间空两格占位,共 10 项,注意 40 拼作 forty 而不是 fourty;第三张是级差名:thousand、million、billion、trillion、quadrillion、quintillion、sextillion、septillion、octillion、nonillion、decillion,共 11 项,每往上一级乘 1000。三张表加起来只有 41 个英文单词,却覆盖了到 1033 的全部整数。
命名体系用的是英语短级差(short scale)。它规定 billion = 109、trillion = 1012,每一级 = 上一级 × 1000。历史上英国长期使用长级差(long scale),把 billion 当 1012、trillion 当 1018,于是同一个 billion 在大西洋两岸差了 1000 倍。1974 年之后英国官方与主流词典统一改用短级差,现在英美两国一致,本页也按短级差输出。
转换过程分四步,全部在字符串上做:① 先剥掉正负号,把整数部分按小数点切开;② 从右往左每 3 位切一组,得到若干个 0~999 的小组,低位组在前;③ 每个小组内部再拆成百位与低两位,低两位小于 20 查第一张表、20 及以上拆成「整十 + 连字符 + 个位」;④ 把小组按级差名从高到低拼起来。整个过程不经过浮点运算,所以位数再长也不会被舍入。
英式 and 的插入位置是有讲究的。规则是两条:其一,某个小组内部百位后面还有低两位时,在百位和低两位之间插 and,所以 234 是 two hundred and thirty-four;其二,整个数的高位组后面只剩一个 1~99 的尾组时,尾组前面补 and,所以 1001 是 one thousand and one、1000001 是 one million and one。两条规则合起来意味着 100 末尾不加 and(one hundred),1234 的低位组是 234 不属于 1~99,也不再补第二个 and。1 到 100 之间含有连字符的整数一共 72 个——21 到 99 去掉 20、30、40、50、60、70、80、90 这 8 个整十,剩下的 72 个都要写连字符。
为什么用字符串分组而不是位运算。JavaScript 的按位运算会把操作数先转成 32 位有符号整数,(x / 1000) | 0 这种写法在 x 超过 2147483647 之后就开始出错。用它去分组 9007199254740991,只会得到 4 组而不是正确的 6 组。本页全程用 Math.floor 与切片,避开这个坑。
完整示例(默认值 1234)
示例条件就是页面打开时的默认状态:数字 1234,勾选「英式 and」与「21~99 加连字符」,不勾「首字母大写」。
- 输出
one thousand two hundred and thirty-four; - 单词个数 7(one / thousand / two / hundred / and / thirty / four);
- 字符数 40,其中的连字符 1 个;
- 命名级数 2,也就是 thousand 组和个位组各一个;
- 把「英式 and」取消勾选,同一串变成
one thousand two hundred thirty-four,单词个数降到 6、字符数降到 36,少了 and 这一个词和后面那个空格; - 把「21~99 加连字符」也取消,得到
one thousand two hundred and thirty four,字符数仍是 40——连字符变空格不改变长度,只是把 thirty 和 four 拆成两个词。
再看一个把三条规则同时用上的例子:1234567 拼成 one million two hundred and thirty-four thousand five hundred and sixty-seven,共 13 个单词、77 个字符,两个 and 分别来自 234 和 567 这两个三位小组。
输入范围与命名对照表
下表列出短级差命名的全部 11 级。每一级都等于上一级乘 1000,所以「级差表」其实是一条等比数列。
| 10 的幂 | 英文名称 | 该级起点(完整数字) | 与上一级的关系 |
|---|---|---|---|
| 103 | thousand | 1000 | 起点 |
| 106 | million | 1000000 | 1000 thousand |
| 109 | billion | 1000000000 | 1000 million |
| 1012 | trillion | 1000000000000 | 1000 billion |
| 1015 | quadrillion | 1000000000000000 | 1000 trillion |
| 1018 | quintillion | 1000000000000000000 | 1000 quadrillion |
| 1021 | sextillion | 1000000000000000000000 | 1000 quintillion |
| 1024 | septillion | 1000000000000000000000000 | 1000 sextillion |
| 1027 | octillion | 1000000000000000000000000000 | 1000 septillion |
| 1030 | nonillion | 1000000000000000000000000000000 | 1000 octillion |
| 1033 | decillion | 1000000000000000000000000000000000 | 1000 nonillion |
再往下依次是 undecillion(1036)、duodecillion(1039)、tredecillion(1042),命名规则一样,只是本工具永远用不到——输入的整数上限卡在 9007199254740991,还不到 1016,也就是刚过 quadrillion 一级。
第二张表把三条规则的开关差异摆在一起。英式列是默认状态(and + 连字符),美式列关掉了 and,最后一列只关连字符:
| 数字 | 英式 and + 连字符(默认) | 美式(无 and) | 无连字符 |
|---|---|---|---|
| 21 | twenty-one | twenty-one | twenty one |
| 42 | forty-two | forty-two | forty two |
| 99 | ninety-nine | ninety-nine | ninety nine |
| 100 | one hundred | one hundred | one hundred |
| 101 | one hundred and one | one hundred one | one hundred and one |
| 234 | two hundred and thirty-four | two hundred thirty-four | two hundred and thirty four |
| 1001 | one thousand and one | one thousand one | one thousand and one |
| 1234 | one thousand two hundred and thirty-four | one thousand two hundred thirty-four | one thousand two hundred and thirty four |
边界、精度与舍入说明
- 整数上限是 9007199254740991,也就是 253−1。这是 IEEE 754 双精度浮点数能精确表示并且精确运算的最大整数(
Number.MAX_SAFE_INTEGER),比它大一位就进入「能表示但不能保证运算正确」的区间。超限时本页直接报错,不会给你一个看着对、其实错的拼写。 - 越界之后相邻整数会塌缩成同一个值。双精度只有 53 位有效二进制位,253 与 253+1 在内存里是同一个数:9007199254740992 与 9007199254740993 拼出来完全一样。所以在数字框里敲 9007199254740993,你拿到的是 9007199254740992 的英文单词——数值在进入函数之前就已经被改掉了,任何拼写算法都救不回来。
- 上限那一档的规模可以参考。9007199254740991 拼出来是
nine quadrillion seven trillion one hundred and ninety-nine billion two hundred and fifty-four million seven hundred and forty thousand nine hundred and ninety-one,共 26 个单词、163 个字符。 - 1016 仍然能精确表示,但已经不安全。
Number.isSafeInteger(10**16)返回false,尽管 1016 恰好落在双精度可精确表示的格点上。区别在于:它本身没错,但对它做加减法就可能不再准确。做金额、ID 这类需要连续加一的场景,安全上限就是 253−1。 - 再往上连 10 的整数次幂都会失真。把 1024 交给 JavaScript,实际存进去的是 999999999999999983222784,少了大约 1.68×107。这也是本页把上限死死卡在 253−1 的原因——与其给一个印错的单词,不如直接告诉你超范围。
- 阶乘一类的组合数很快撞线。18! = 6402373705728000 还在安全区间内,19! = 121645100408832000 就已经越界了。如果你要换算的是阶乘、排列组合之类的结果,先确认它是否落在 253−1 以内。
- 小数部分按位读,不做「分数化」。输入 3.14 输出
three point one four,而不是 three and fourteen hundredths;12.05 输出twelve point zero five,小数点后那个 0 也要念出来。这符合口语里读小数的习惯,也是本页刻意的取舍——如果要做分数读法,得先约分再取最小分母,是另一套完全不同的算法。 - 负数在前面加 minus。−1234 输出
minus one thousand two hundred and thirty-four,不加括号也不写 negative。 - 本页只做字符串拼接,不做任何舍入。结果是逐字符拼出来的,不存在「四舍五入到几位」的问题;所有精度损失都发生在数字被输入框读进来那一刻,本页能做的只是把超限挡在门外。
- 0 与空值要分清。0 是合法输入,输出
zero;输入框为空则报错,不会悄悄按 0 处理。
常见问题
为什么 42 拼成 forty-two,而不是 fourty-two?
因为英语词典里 40 的正字法就是 forty,不带 u,这是从古英语 feowertig 演变时丢掉字母留下的历史拼法,只有 four、fourteen、four hundred 保留 u。数字转英文单词的第二张整十表把 forty 写死成固定项,所以 40、41、42 …… 直到 49 都会跟着正确输出。
英式 and 到底加在哪儿?1234 里为什么只有一个 and?
两条插入规则:小组内部百位与低两位之间要加(234 → two hundred and thirty-four);高位组后面只剩 1~99 的尾组时,尾组前要加(1001 → one thousand and one)。1234 的尾组是 234,不属于 1~99,所以只有小组内部那一个 and,全串一个。
1000001 为什么是 one million and one,中间那些 0 去哪了?
三位分组后是 1 | 000 | 001,中间那个 000 组的值是 0,工具直接跳过不输出任何单词,也不输出级差名——英语里没有「零千」的说法。剩下两个非零组是百万组和个位组,尾组值 1 属于 1~99,于是在前面补一个 and。
输入 9007199254740993,为什么得到的是 9007199254740992 的单词?
因为数值在进入拼写算法之前就已经被 JavaScript 改掉了。双精度浮点数只有 53 位有效位,253 到 254 之间的可表示整数间隔是 2,9007199254740993 会就近塌缩到 9007199254740992。本页的上限设在 9007199254740991(253−1),填 9007199254740993 会被直接判为超范围并给出提示。
小数为什么读成 three point one four,不是 three and fourteen hundredths?
后者是分数的读法,需要先把 0.14 约分成 7/50 再取分母的序数词,而 0.333… 这类无限小数根本约不出整数分母。数字转英文单词统一按「整数部分 + point + 逐位读小数」处理,既能覆盖任意长度的小数,也与英语口语里的读法一致。
billion 在这个工具里是十亿还是万亿?
十亿,也就是 109。本页用的是短级差(short scale):thousand 103、million 106、billion 109、trillion 1012,每级乘 1000。旧的长级差把 billion 当 1012,同一个词相差 1000 倍,英国在 1974 年后也统一到短级差了。
关掉「21~99 加连字符」有什么实际影响?
只影响 21 到 99 之间不是整十的 72 个数。连字符在这种情况下是正字法要求,关掉之后 twenty-one 变成 twenty one,长度不变、单词个数从 1 个变成 2 个,做词频统计或逐词比对时会得到不同结果。
0、负数和 0.5 分别输出什么?
0 输出 zero;负数在最前面加 minus,−1234 得到 minus one thousand two hundred and thirty-four;0.5 输出 zero point five,前面的 0 不会被省略,只有小数点后跟着 0 的数才会把这个 0 念成 zero(12.05 → twelve point zero five)。
相关工具
- 古罗马数字转换器:把同一个数写成罗马数字,做章节号和年份标注时用它更合适。
- 中文数字转阿拉伯数字:反方向处理「一千二百三十四」「五亿」这类中文写法。
- 人民币大写转换:把金额转成壹仟贰佰叁拾肆元伍角陆分,填补中文票据那一栏。
- 四舍五入计算器:先把小数按位数修约,再来拼英文单词,避免把一长串不可靠的小数位念出来。
- 阶乘计算器:算完先看一眼结果有没有超过 9007199254740991,再决定能不能用本页拼写。
- 十进制转二进制转换器:同样是位值分解,看双精度 53 位有效位在不同进制下长什么样。
- 计算器:查看全部计算器工具。