如何使用工程计数法格式化数字

使用工程计数法以与 SI 单位前缀对齐的指数形式显示数字

引言

工程计数法是一种用 10 的幂来表示数字的方法,其中指数始终为 3 的倍数。例如,123,000,000 在科学计数法中写作 1.23×10⁸,而在工程计数法中则表示为 123×10⁶。这种以 3 的倍数为指数的方式,与国际单位制(SI)前缀如 kilo(10³)、mega(10⁶)、giga(10⁹)相对应。

在工程、电子和科学领域中,工程计数法经常用于带有 SI 前缀的计量单位。例如,标称为 4.7×10⁻⁶ 法拉的电容器可表示为 4.7 微法拉;频率为 2.4×10⁹ 赫兹可表示为 2.4 吉赫兹。工程计数法使这些换算变得直观,因为指数直接对应 SI 前缀。

JavaScript 通过内置的 Intl.NumberFormat API 提供了对工程计数法的支持。该 API 能自动完成转换,并根据不同的语言和地区调整格式。

什么是工程计数法

工程计数法将数字表示为系数乘以 10 的幂,且指数始终为 3 的倍数。例如,987,654,321 在工程计数法中写作 987.654×10⁶,在 JavaScript 输出中为 987.654E6。

系数为 1 到 999.999 之间的数字,后跟 E 和指数。E 代表 exponent(指数),表示乘以 10 的相应幂。例如,987.654E6 表示 987.654 × 10⁶,即 987,654,000。

这种格式不同于标准小数记法(如 987,654,321,带有分隔符),也不同于紧凑记法(如用 K、M、B 表示数量级)。工程计数法通过指数形式明确显示 10 的幂。

为什么工程计数法使用 3 的倍数

之所以限定为 3 的倍数,是因为 SI 单位前缀每次都是以 1000 为倍数递增或递减。每向上一个前缀,指数就乘以 10³,每向下一个前缀,指数就除以 10³。

来看一下 10 的幂次对应的 SI 前缀:

  • 10³ = kilo (k)
  • 10⁶ = mega (M)
  • 10⁹ = giga (G)
  • 10¹² = tera (T)
  • 10⁻³ = milli (m)
  • 10⁻⁶ = micro (μ)
  • 10⁻⁹ = nano (n)
  • 10⁻¹² = pico (p)

当一个数字用工程计数法表示且指数为 6 时,你就知道它对应的是 mega 前缀。指数为 -9 时,对应的就是 nano 前缀。这种直接对应关系让工程计数法在以 SI 单位为主的技术领域非常实用。

如果没有这个限制,你就需要心算来在计数法和 SI 前缀之间换算。有了这个限制,转换就可以直接完成。

工程计数法与科学计数法的区别

科学计数法同样用 10 的幂次来表示数字,但它使用最小可能的指数。比如数字 987,654,321 在科学计数法中写作 9.87654321×10⁸,记作 9.87654321E8。

科学计数法总是保证小数点前只有一个非零数字。工程计数法则允许小数点前最多有三位数字,以确保指数能被 3 整除。

const scientificFormatter = new Intl.NumberFormat("en-US", {
  notation: "scientific"
});

console.log(scientificFormatter.format(987654321));
// Output: "9.877E8"

const engineeringFormatter = new Intl.NumberFormat("en-US", {
  notation: "engineering"
});

console.log(engineeringFormatter.format(987654321));
// Output: "987.654E6"

科学计数格式器会生成 9.877E8,只保留小数点前一位数字。工程计数格式器会生成 987.654E6,将三位数字放在小数点前,使指数变为 6 而不是 8。

这两种记法表示相同的数值,但工程记数法优先与 SI 前缀对齐,而不是最小化指数。

在 JavaScript 中使用工程记数法

notation 选项在 Intl.NumberFormat 中用于控制数字的表示方式。将其设置为 "engineering" 可启用工程记数法。

const formatter = new Intl.NumberFormat("en-US", {
  notation: "engineering"
});

console.log(formatter.format(1500));
// Output: "1.5E3"

console.log(formatter.format(1500000));
// Output: "1.5E6"

console.log(formatter.format(1500000000));
// Output: "1.5E9"

格式化器会根据数字的数量级自动选择合适的指数。指数始终为 3 的倍数,以确保与 SI 前缀对齐。

你无需手动计算正确的指数或系数。Intl API 会根据数字的值自动处理这些计算。

工程记数法如何格式化不同数量级

工程记数法适用于所有数量级,从极小到极大的数字。了解不同数量级如何映射到指数,有助于你预测输出结果。

const formatter = new Intl.NumberFormat("en-US", {
  notation: "engineering"
});

console.log(formatter.format(0.0015));
// Output: "1.5E-3"

console.log(formatter.format(0.0000015));
// Output: "1.5E-6"

console.log(formatter.format(1.5));
// Output: "1.5E0"

console.log(formatter.format(1500));
// Output: "1.5E3"

console.log(formatter.format(1500000));
// Output: "1.5E6"

console.log(formatter.format(1500000000));
// Output: "1.5E9"

console.log(formatter.format(1500000000000));
// Output: "1.5E12"

小于 1 的数字使用负指数。例如,0.0015 会变为 1.5E-3,对应于 milli 前缀。0.0000015 会变为 1.5E-6,对应于 micro 前缀。

接近 1 的数字使用 0 作为指数。例如,1.5 会变为 1.5E0,即 1.5 × 10⁰ = 1.5 × 1 = 1.5。

较大的数字使用正指数。例如,1500 会变为 1.5E3,对应于 kilo 前缀。该模式会继续应用于 mega、giga 和 tera。

控制工程记数法中的小数位数

默认情况下,格式化器会在系数中包含若干小数位。你可以通过 minimumFractionDigitsmaximumFractionDigits 选项来控制精度。

const defaultFormatter = new Intl.NumberFormat("en-US", {
  notation: "engineering"
});

console.log(defaultFormatter.format(1234567));
// Output: "1.235E6"

const noDecimalsFormatter = new Intl.NumberFormat("en-US", {
  notation: "engineering",
  maximumFractionDigits: 0
});

console.log(noDecimalsFormatter.format(1234567));
// Output: "1E6"

const twoDecimalsFormatter = new Intl.NumberFormat("en-US", {
  notation: "engineering",
  maximumFractionDigits: 2
});

console.log(twoDecimalsFormatter.format(1234567));
// Output: "1.23E6"

maximumFractionDigits 选项用于限制系数小数点后的位数。将其设置为 0 时,所有小数位都会被移除,仅显示系数的整数部分。

您还可以强制设置最小小数位数,以便在多个数字之间保持格式一致。

const formatter = new Intl.NumberFormat("en-US", {
  notation: "engineering",
  minimumFractionDigits: 2,
  maximumFractionDigits: 2
});

console.log(formatter.format(1000));
// Output: "1.00E3"

console.log(formatter.format(1500));
// Output: "1.50E3"

console.log(formatter.format(1234567));
// Output: "1.23E6"

这样可以确保所有数字都显示为两位小数,有助于在表格和报告中保持视觉一致性。

工程计数法在不同语言环境下的工作方式

工程计数法会根据不同语言环境的十进制分隔符习惯进行调整。指数格式保持一致,但系数的格式会根据本地习惯变化。

const enFormatter = new Intl.NumberFormat("en-US", {
  notation: "engineering"
});

console.log(enFormatter.format(1234567));
// Output: "1.235E6"

const deFormatter = new Intl.NumberFormat("de-DE", {
  notation: "engineering"
});

console.log(deFormatter.format(1234567));
// Output: "1,235E6"

const frFormatter = new Intl.NumberFormat("fr-FR", {
  notation: "engineering"
});

console.log(frFormatter.format(1234567));
// Output: "1,235E6"

英文中,系数的小数分隔符为句点。德语和法语中,小数分隔符为逗号。E 和指数在所有语言环境下都保持不变。

本地化仅适用于系数部分。指数记号(E 和指数值)遵循国际科学惯例,在不同语言环境下不会变化。

工程计数法与其他格式化选项的结合

工程计数法可与其他数字格式化选项配合使用。您可以在使用工程计数法时控制四舍五入、有效数字和符号显示。

const formatter = new Intl.NumberFormat("en-US", {
  notation: "engineering",
  signDisplay: "always"
});

console.log(formatter.format(1500000));
// Output: "+1.5E6"

console.log(formatter.format(-1500000));
// Output: "-1.5E6"

signDisplay 选项用于控制正数是否显示加号。将其设置为 "always" 时,正负数都会显示符号。

您还可以选择控制有效数字位数,而不是小数位数。

const formatter = new Intl.NumberFormat("en-US", {
  notation: "engineering",
  minimumSignificantDigits: 4,
  maximumSignificantDigits: 4
});

console.log(formatter.format(1234567));
// Output: "1.235E6"

console.log(formatter.format(1567890));
// Output: "1.568E6"

minimumSignificantDigitsmaximumSignificantDigits 选项用于控制系数的总有效数字数,而不仅仅是小数位数。

何时使用工程计数法

工程计数法最适用于技术场景,特别是涉及 SI 单位前缀的测量。电子文档、科学论文和工程规范中常用此记数法。

在记录带有 4.7×10⁻⁶ 法拉电容器的电路时,工程计数法会将其表示为 4.7E-6。工程师会立即识别为 4.7 微法拉。当显示 2.4×10⁹ 赫兹的频率时,工程计数法会写作 2.4E9,工程师会理解为 2.4 吉赫兹。

这种记数法不太适合普通大众,因为他们可能不理解指数表示法。社交媒体计数器、电商价格和面向消费者的仪表盘应使用标准记数法或紧凑记数法。

在精度至关重要且每一位数字都很重要的场合,不要使用工程计数法。财务计算、法律文件和审计记录需要精确的小数表示。例如,银行余额应显示为 $1,234.56,而不是 1.23456E3。

请考虑你的受众。工程师、物理学家和技术专业人员习惯并理解工程计数法。普通消费者则更容易阅读标准记数法或紧凑记数法。