先记住这个答案
Intl.NumberFormat 的 notation 选项控制记数法,有四个取值:默认的 standard 就是普通写法;scientific 是科学计数法,系数只有一位整数,987654321 显示成 9.877E8;而 engineering 是工程计数法,指数总是 3 的倍数,显示成 987.7E6;最后的 compact 是紧凑写法,中文显示「9.9亿」,英文显示「988M」。科学计数法和工程计数法的精度由有效数字决定,通常配合 maximumSignificantDigits 使用。
scientific是一位整数加指数,如9.877E8engineering指数是 3 的倍数,如987.7E6compact是「9.9亿」这种面向普通用户的缩写- 精度用
maximumSignificantDigits控制
科学计数法和工程计数法
同一个数,两种记数法表达的数量级一样,只是指数的选法不同。
notationJavaScriptconst value = 987654321
const show = (notation, extra = {}) =>
new Intl.NumberFormat('en-US', { notation, ...extra }).format(value)
console.log(show('scientific', { maximumSignificantDigits: 4 })) // 9.877 × 10^8
console.log(show('engineering', { maximumSignificantDigits: 4 })) // 987.7 × 10^6
console.log(show('compact')) // 给普通用户看的缩写
console.log(new Intl.NumberFormat('zh-CN', { notation: 'compact' }).format(value))
console.log(new Intl.NumberFormat('en-US', { notation: 'engineering' }).format(0.000123))查看输出与解释
9.877E8
987.7E6
988M
9.9亿
123E-6科学计数法把小数点移到第一位数字后面,指数是 8。工程计数法要求指数是 3 的倍数,所以取 6,系数变成 987.7。3 的倍数正好对应千(k)、百万(M)、微(µ)这些单位前缀,所以 123E-6 一眼就能读成 123 微,这是工程领域偏爱它的原因。
compact 不是科学计数法,而是按语言习惯缩写。中文按「万」「亿」进位,英文按 K、M、B 进位,适合粉丝数、播放量这类给普通用户看的数字。
精度要用有效数字控制
科学计数法下,控制精度最直接的是有效数字。用小数位数去控制,数量级一变,保留下来的精度也跟着变。
const sci = (opts) => new Intl.NumberFormat('en-US', { notation: 'scientific', ...opts })
console.log(sci({ maximumSignificantDigits: 3 }).format(987654321))
console.log(sci({ maximumSignificantDigits: 3 }).format(0.000123456))
// toExponential 也能出指数形式,但格式固定,不按语言处理
console.log((987654321).toExponential(2))查看输出与解释
9.88E8
1.23E-4
9.88e+8maximumSignificantDigits: 3 表示总共保留 3 位有效数字,不管数字多大多小,精度都一样。测量数据、统计结果通常按有效数字来要求精度。
toExponential() 是 Number 自带的方法,也能输出指数形式,但格式写死成 e+8 这种程序员写法,不会按语言处理小数点,也没法设置有效数字。给用户看用 Intl.NumberFormat,写日志或调试用 toExponential() 就够了。
- 指数部分单独渲染
- 界面上想把指数显示成上标 10⁸,可以用
formatToParts()。它会返回integer、fraction、exponentSeparator、exponentMinusSign和exponentInteger这些片段,把exponentSeparator换成「× 10」,再把exponentInteger放进<sup>就行。
容易答错的地方
- 把
compact当成科学计数法 compact输出「9.9亿」「988M」,是面向普通用户的语言缩写,规则因语言而异。scientific输出9.877E8,是面向技术场景的固定格式。需求说「大数字缩写显示」时通常要的是compact。- 以为
engineering和scientific指数一样 - 两者的指数一般不同。987654321 在科学计数法里是
E8,在工程计数法里是E6,因为工程计数法只取 3 的倍数,多出来的位数挪到了系数上。
面试官还会怎么问?
格式化会改变原来的数字吗?
不会。format() 只返回一个舍入后的字符串,原来的 Number 不变。但用户看到的精度降低了,所以不要从显示文本反推原值,接口和存储始终传原始数值。
compact 的缩写能改成完整的词吗?
可以,加 compactDisplay: 'long'。英文会从 988M 变成 988 million;中文本来就是「亿」这类汉字,差别不大。
为什么科学计数法的默认结果是 9.877E8,不是更多位?
scientific 模式下默认最多保留 3 位小数,所以系数是 9.877。需要更多位时,显式设置 maximumFractionDigits 或者 maximumSignificantDigits。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。