如何在 JavaScript 中将数字格式化为两位小数
为价格、百分比和测量值显示精确到两位小数的数字
介绍
许多应用程序需要以固定的小数位数显示数字。例如,价格通常显示为两位小数,如 $19.99。百分比通常显示为 45.50%。测量值为了便于阅读也会使用一致的小数位数,如 3.14 米。
控制小数位数可以确保应用程序中视觉上的一致性。如果没有明确的格式化,JavaScript 会根据实际值显示不同的小数位数。例如,数字 5 显示为 "5",而 5.5 显示为 "5.5",这会导致对齐和外观的不一致。
本课程将展示如何将数字格式化为精确的 2 位小数,或最多 2 位小数,同时尊重不同语言环境的约定。
使用 toFixed() 进行基本格式化
toFixed() 方法将数字转换为具有指定小数位数的字符串。将小数位数作为参数传递。
const price = 19.9;
const formatted = price.toFixed(2);
console.log(formatted);
// 输出: "19.90"
该方法始终显示精确的 2 位小数。如果数字的小数位数少于 2 位,toFixed() 会用零填充。如果小数位数多于 2 位,该方法会四舍五入到 2 位。
const examples = [5, 5.5, 5.555, 5.999];
examples.forEach(num => {
console.log(num.toFixed(2));
});
// 输出:
// "5.00"
// "5.50"
// "5.56"
// "6.00"
toFixed() 方法返回的是字符串,而不是数字。这是有意为之,因为尾随的零对于显示有意义,但如果返回数字则会丢失。
toFixed() 的语言环境问题
toFixed() 方法始终使用句点作为小数分隔符,而不考虑用户的语言环境。许多国家使用逗号作为小数分隔符,而不是句点。
const price = 19.99;
console.log(price.toFixed(2));
// 输出: "19.99" (始终使用句点)
对于德国、法国、西班牙和许多其他国家的用户来说,这看起来是错误的。他们期望看到 "19,99" 而不是 "19.99"。toFixed() 方法无法生成符合语言环境的输出。
要为不同的语言环境正确格式化数字,请使用 Intl.NumberFormat API。
使用 Intl.NumberFormat 进行符合本地习惯的格式化
Intl.NumberFormat API 根据本地化习惯格式化数字。通过指定一个语言环境和选项创建格式化器,然后使用数字调用其 format() 方法。
const formatter = new Intl.NumberFormat("de-DE", {
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
const price = 19.99;
console.log(formatter.format(price));
// 输出: "19,99" (德语环境使用逗号作为小数点)
相同的格式化器在不同的语言环境下会产生不同的输出。
const price = 19.99;
const usFormatter = new Intl.NumberFormat("en-US", {
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
const deFormatter = new Intl.NumberFormat("de-DE", {
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
console.log(usFormatter.format(price));
// 输出: "19.99"
console.log(deFormatter.format(price));
// 输出: "19,99"
小数点分隔符会根据语言环境自动更改。
格式化为精确的两位小数
要显示精确的两位小数,请将 minimumFractionDigits 和 maximumFractionDigits 都设置为 2。这确保输出始终有两位小数,必要时用零填充,并在数字精度更高时进行四舍五入。
const formatter = new Intl.NumberFormat("en-US", {
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
console.log(formatter.format(5));
// 输出: "5.00"
console.log(formatter.format(5.5));
// 输出: "5.50"
console.log(formatter.format(5.555));
// 输出: "5.56"
minimumFractionDigits 选项控制尾随零。如果不设置,位数较少的小数将不会显示零。
const withoutMinimum = new Intl.NumberFormat("en-US", {
maximumFractionDigits: 2
});
console.log(withoutMinimum.format(5));
// 输出: "5"
const withMinimum = new Intl.NumberFormat("en-US", {
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
console.log(withMinimum.format(5));
// 输出: "5.00"
将两个选项设置为相同的值可以确保所有数字的十进制位数一致。
格式化为最多两位小数
有时您只希望在需要时显示小数位,最多显示两位。将 maximumFractionDigits 设置为 2,并将 minimumFractionDigits 设置为 0 或完全省略。
const formatter = new Intl.NumberFormat("en-US", {
minimumFractionDigits: 0,
maximumFractionDigits: 2
});
console.log(formatter.format(5));
// 输出: "5"
console.log(formatter.format(5.5));
// 输出: "5.5"
console.log(formatter.format(5.555));
// 输出: "5.56"
这种方法去除了尾随零,但仍将精度限制为两位小数。它非常适合显示测量值或统计数据,其中尾随零没有信息价值。
对于普通数字格式化,minimumFractionDigits 的默认值为 0,因此可以省略。
const formatter = new Intl.NumberFormat("en-US", {
maximumFractionDigits: 2
});
console.log(formatter.format(5));
// 输出: "5"
console.log(formatter.format(5.5));
// 输出: "5.5"
重用格式化器以提高性能
创建一个新的 Intl.NumberFormat 实例的开销相对较大。如果需要使用相同的选项格式化多个数字,请只创建一次格式化器并重复使用。
const formatter = new Intl.NumberFormat("en-US", {
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
const prices = [19.99, 29.5, 99, 149.999];
prices.forEach(price => {
console.log(formatter.format(price));
});
// 输出:
// "19.99"
// "29.50"
// "99.00"
// "150.00"
这种模式比为每个数字创建一个新的格式化器更高效。
何时使用每种方法
在显示价格、货币金额或小数位具有语义意义的任何值时,使用精确到 2 位小数的格式。显示 "$5.00" 而不是 "$5" 表明了精确性,并符合用户对价格的预期。
在显示统计数据、测量值或计算值时,使用最多 2 位小数的格式,其中尾随零不提供额外信息。显示 "5 米" 而不是 "5.00 米" 更简洁且更易读。
仅在确定所有用户都使用相同的小数分隔符约定时,或输出不面向用户时,使用 toFixed()。对于国际化应用程序,优先使用 Intl.NumberFormat。
使用用户的首选区域设置
与其硬编码区域设置,不如使用用户的浏览器语言偏好。navigator.language 属性提供了用户的首选区域设置。
const formatter = new Intl.NumberFormat(navigator.language, {
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
const price = 19.99;
console.log(formatter.format(price));
// 输出因用户的区域设置而异
// 对于 en-US: "19.99"
// 对于 de-DE: "19,99"
// 对于 fr-FR: "19,99"
您还可以传递整个 navigator.languages 数组,让 Intl API 从用户的偏好中选择第一个支持的区域设置。
const formatter = new Intl.NumberFormat(navigator.languages, {
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
这种方法在用户的首选项不受支持时提供了自动回退。