如何使用有效数字格式化数字

通过指定精度,控制格式化数字中显示和四舍五入的数字位数

简介

在格式化数字以供显示时,有时需要根据数字中包含多少有意义的数字位来控制精度,而不是仅仅关注小数点后的位数。这种方法称为使用有效数字进行格式化。

有效数字是指一个数字中能够反映其精度的信息位。例如,数字 123.45 有五位有效数字。数字 0.00123 有三位有效数字,因为前导零只表示数量级,而不代表精度。

本课程将向你展示如何在 JavaScript 中使用有效数字格式化数字。你将了解在何种情况下这种方法优于仅控制小数位数,并学习如何结合 Intl.NumberFormat API 的 minimumSignificantDigitsmaximumSignificantDigits 选项来实现。

什么是有效数字

有效数字是指一个数字中能够反映其精度的数字。判断哪些数字是有效数字需要遵循特定规则。

所有非零数字都是有效数字。例如,数字 123 的三位数字都是有效数字。45.67 的四位数字也都是有效数字。

前导零永远不是有效数字。它们只表示小数点的位置。例如,0.0045 中,只有 4 和 5 是有效数字,这个数字有两位有效数字,而不是六位。

小数点后的尾随零是有效数字。它们表示测量或计算的精度达到该位。例如,数字 1.200 有四位有效数字,而 1.2 只有两位。

小数点前的末尾零是否有意义取决于具体上下文。在数字 1200 中,如果没有额外信息,无法判断这些零是否为有效数字。可以通过科学计数法或明确的精度指示来消除这种歧义。

使用最大有效数字格式化数字

maximumSignificantDigits 选项用于限制格式化输出中显示的有效数字位数。无论数字的数量级如何,该选项都能帮助你以一致的精度显示数字。

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

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

console.log(formatter.format(12.345));
// Output: "12.3"

console.log(formatter.format(123.45));
// Output: "123"

console.log(formatter.format(1234.5));
// Output: "1,230"

当数字的有效数字多于最大值时,格式化器会对数字进行四舍五入。四舍五入遵循标准规则,即四舍五入到最接近的值。如果数字正好位于两个值的中间,则会四舍五入到最接近的偶数。

maximumSignificantDigits 选项可接受 1 到 21 之间的数值。如果未指定该选项,默认值为 21,即实际上没有限制。

const oneDigit = new Intl.NumberFormat("en-US", {
  maximumSignificantDigits: 1,
});

console.log(oneDigit.format(54.33));
// Output: "50"

console.log(oneDigit.format(56.33));
// Output: "60"

该选项适用于所有数字类型,包括整数、小数以及不同记数法的数字。

使用最小有效数字格式化数字

minimumSignificantDigits 选项可确保格式化输出中至少包含指定数量的有效数字。当数字的有效数字少于最小值时,格式化器会在末尾补零。

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

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

console.log(formatter.format(123));
// Output: "123.00"

console.log(formatter.format(0.0012));
// Output: "0.0012000"

当你需要以一致的精度显示数字,或需要表明测量或计算已达到特定精度时,该选项非常有用。

minimumSignificantDigits 选项可接受 1 到 21 之间的数值。默认值为 1,表示数字以其自然精度显示,不会额外补零。

const manyDigits = new Intl.NumberFormat("en-US", {
  minimumSignificantDigits: 10,
});

console.log(manyDigits.format(5));
// Output: "5.000000000"

格式化器会在小数点后补零以达到最小位数,或在必要时在小数点前补零。

结合最小和最大有效数字

你可以同时指定 minimumSignificantDigitsmaximumSignificantDigits,以创建一个可接受的精度范围。格式化器会在此范围内显示数字。

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

console.log(formatter.format(1.2));
// Output: "1.20"
// Expanded to meet minimum of 3

console.log(formatter.format(1.234));
// Output: "1.234"
// Within range, displayed as-is

console.log(formatter.format(1.23456789));
// Output: "1.2346"
// Rounded to meet maximum of 5

在组合这些选项时,最小值必须小于或等于最大值。如果你指定的最小值大于最大值,格式化器会抛出 RangeError。

try {
  const invalid = new Intl.NumberFormat("en-US", {
    minimumSignificantDigits: 5,
    maximumSignificantDigits: 3,
  });
} catch (error) {
  console.log(error.name);
  // Output: "RangeError"
}

这种组合对于需要同时保证最小精度并防止过多数字影响显示的科学或金融应用尤其有用。

有效数字与小数位数的区别

有效数字和小数位数是控制数字精度的两种不同方式。了解何时使用每种方式有助于你正确格式化数字。

小数位数控制小数点后显示多少位数字,而不考虑数字的数量级。选项 minimumFractionDigitsmaximumFractionDigits 实现了这种方式。

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

console.log(decimalPlaces.format(1.2));
// Output: "1.20"

console.log(decimalPlaces.format(12.3));
// Output: "12.30"

console.log(decimalPlaces.format(123.4));
// Output: "123.40"

有效数字控制整个数字中有意义的数字位数,并根据数字的数量级进行调整。不同数量级的数字会显示不同的小数位数,以保持精度一致。

const significantDigits = new Intl.NumberFormat("en-US", {
  minimumSignificantDigits: 3,
  maximumSignificantDigits: 3,
});

console.log(significantDigits.format(1.2));
// Output: "1.20"

console.log(significantDigits.format(12.3));
// Output: "12.3"

console.log(significantDigits.format(123.4));
// Output: "123"

请注意,有效数字方式在数字数量级增加时会显示更少的小数位,而小数位方式无论数量级如何都显示相同的小数位数。

与小数位选项的交互

当你指定有效数字选项时,默认情况下它们优先于小数位数选项。当存在任一有效数字选项时,格式化器会忽略 minimumFractionDigitsmaximumFractionDigits

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

console.log(formatter.format(1234.56));
// Output: "1,230"
// Significant digits option takes precedence
// Fraction digit options are ignored

此行为由 roundingPriority 选项控制,该选项决定格式化器在不同精度设置冲突时的处理方式。默认值为 "auto",即优先考虑有效数字。

你可以将 roundingPriority 设置为 "morePrecision" 或 "lessPrecision" 来更改此行为,但这些是针对特殊场景的高级选项。对于大多数应用,默认的优先级行为是合适的。

何时使用有效数字而非小数位数

当你需要在不同数量级的数字间保持一致精度时,应选择有效数字。这种方式在科学、工程和数据可视化领域很常见。

在科学测量和计算中应使用有效数字。实验室结果、传感器读数和物理测量通常需要反映测量仪器的精度。始终显示三位有效数字,无论测量值是 0.0123、1.23 还是 123,都能准确传达精度。

const measurement = new Intl.NumberFormat("en-US", {
  maximumSignificantDigits: 4,
});

console.log(measurement.format(0.012345));
// Output: "0.01235"

console.log(measurement.format(1.2345));
// Output: "1.235"

console.log(measurement.format(1234.5));
// Output: "1,235"

对于展示不同数量级数字的仪表盘指标,也应使用有效数字。例如页面浏览量、收入或用户数等统计数据,采用有效数字可以避免小数过度精确,同时保证大数易于阅读。

const metric = new Intl.NumberFormat("en-US", {
  maximumSignificantDigits: 3,
});

console.log(metric.format(1.234));
// Output: "1.23"

console.log(metric.format(123.4));
// Output: "123"

console.log(metric.format(12345));
// Output: "12,300"

对于货币和金融金额等需要分数部分表示分币或其他固定货币单位的场景,应使用小数位数。无论数值大小,这些金额都需要保持一致的小数位数。

const currency = new Intl.NumberFormat("en-US", {
  style: "currency",
  currency: "USD",
  minimumFractionDigits: 2,
  maximumFractionDigits: 2,
});

console.log(currency.format(1.5));
// Output: "$1.50"

console.log(currency.format(123.5));
// Output: "$123.50"

选择哪种方式,取决于精度是与总位数相关,还是与固定的小数部分相关。