如何使用千位分隔符格式化数字

使用 JavaScript 显示带有区域设置适当分组符号的大数字

介绍

大数字如果没有视觉分隔会很难阅读。数字 1234567 需要仔细数位才能确定它是代表一百万还是一千万。添加分隔符后,变成 1,234,567,可以立即识别为大约一百万。

不同国家使用不同的符号来分隔数字组。美国人使用逗号,德国人使用句号,而法语使用者使用空格。当您在一个全球用户使用的应用程序中显示数字时,您需要根据每个用户的期望格式化这些数字。

JavaScript 提供了 Intl.NumberFormat API 来自动处理这些问题。本课程将解释千位分隔符的工作原理、为何因地区而异,以及如何为任何语言或地区正确格式化数字。

什么是千位分隔符

千位分隔符是一种插入在数字组之间的符号,用于使大数字更易于阅读。在大多数地区,数字从右到左以三位一组进行分组。数字 1234567 使用逗号分隔符后变成 1,234,567

“千位分隔符”这一术语来源于最常见的用例,即分隔符出现在每三位数字之后。然而,这种机制适用于任何数字分组,无论是数十万、数百万还是数十亿。

没有分隔符时,数字会连在一起,需要仔细数位。有了分隔符,您的眼睛可以快速识别数字的数量级。这种视觉分组减少了阅读错误并提高了理解力。

为什么千位分隔符因地区而异

不同国家建立了不同的书写数字的惯例。这些惯例是基于当地的印刷实践、教育系统和文化偏好独立发展起来的。

在美国、英国和澳大利亚等英语国家,逗号用作千位分隔符。一百万写作 1,000,000

在包括德国、意大利、西班牙和葡萄牙在内的许多欧洲国家,句号用作千位分隔符。同样的数字写作 1.000.000

在法国和许多法语地区,空格用作千位分隔符。数字写作 1 000 000

在瑞士,撇号用作千位分隔符。数字写作 1'000'000

一些国家如印度使用不同的分组模式。印度的数字分组将前三位分组,然后将后续数字按两位分组。一百万写作 10,00,000,使用的是拉克系统。

当您硬编码一个特定的分隔符字符时,您假设所有用户都遵循相同的惯例。这会使您的应用程序对来自不同地区的用户更难使用。

使用 Intl.NumberFormat 添加千位分隔符

Intl.NumberFormat 构造函数创建一个数字格式化器,应用特定语言环境的约定。将语言环境标识符作为第一个参数传递,然后使用一个数字调用 format() 方法。

const formatter = new Intl.NumberFormat('en-US');
console.log(formatter.format(1234567));
// 输出: "1,234,567"

这会创建一个适用于美式英语的格式化器,它使用逗号作为千位分隔符。format() 方法将数字转换为带有适当分隔符的字符串。

通过更改语言环境标识符,可以为不同的语言环境格式化相同的数字。

const usFormatter = new Intl.NumberFormat('en-US');
console.log(usFormatter.format(1234567));
// 输出: "1,234,567"

const deFormatter = new Intl.NumberFormat('de-DE');
console.log(deFormatter.format(1234567));
// 输出: "1.234.567"

const frFormatter = new Intl.NumberFormat('fr-FR');
console.log(frFormatter.format(1234567));
// 输出: "1 234 567"

每个格式化器都会应用其语言环境的约定。德语格式化器使用句点,法语格式化器使用空格,而美式英语格式化器使用逗号。您无需了解每种语言环境使用的符号,API 会自动处理这些细节。

为用户的语言环境格式化数字

与硬编码特定语言环境不同,您可以使用浏览器提供的用户首选语言。navigator.language 属性返回用户的首选语言。

const userLocale = navigator.language;
const formatter = new Intl.NumberFormat(userLocale);

console.log(formatter.format(1234567));
// 输出因用户的语言环境而异
// 对于 en-US: "1,234,567"
// 对于 de-DE: "1.234.567"
// 对于 fr-FR: "1 234 567"

这种方法根据每个用户的期望显示数字,而无需用户手动选择语言环境。浏览器提供语言偏好,Intl API 应用适当的格式化约定。

您还可以传递整个首选语言数组以启用回退行为。

const formatter = new Intl.NumberFormat(navigator.languages);
console.log(formatter.format(1234567));

API 使用数组中支持的第一个语言环境。这在用户的首选语言不可用时提供了更好的回退处理。

了解默认的分组行为

默认情况下,Intl.NumberFormat 会对所有足够大的数字应用千位分隔符,以便分组。通常,具有四位或更多位数的数字会添加分隔符,但这因地区而异。

const formatter = new Intl.NumberFormat('en-US');

console.log(formatter.format(123));
// 输出: "123"

console.log(formatter.format(1234));
// 输出: "1,234"

console.log(formatter.format(12345));
// 输出: "12,345"

console.log(formatter.format(123456));
// 输出: "123,456"

123 这样的小数字不需要分隔符,因此不会显示分隔符。从 1234 开始的数字会添加分隔符,因为分组可以提高可读性。

API 会根据地区惯例自动确定何时需要分隔符。您无需在格式化之前手动检查每个数字的大小。

使用千位分隔符格式化小数

Intl.NumberFormat API 处理数字的整数部分和小数部分。千位分隔符出现在整数部分,而小数点和小数位遵循地区惯例。

const usFormatter = new Intl.NumberFormat('en-US');
console.log(usFormatter.format(1234567.89));
// 输出: "1,234,567.89"

const deFormatter = new Intl.NumberFormat('de-DE');
console.log(deFormatter.format(1234567.89));
// 输出: "1.234.567,89"

请注意,德语格式反转了这两种惯例。句点用作整数部分的千位分隔符,而逗号用作小数部分的小数分隔符。Intl API 会根据地区正确处理这两个方面。

处理非常大的数字

随着数字变得越来越大,千位分隔符变得尤为重要。如果没有分隔符,七位、八位或九位的数字几乎无法一眼准确读取。

const formatter = new Intl.NumberFormat('en-US');

console.log(formatter.format(1234567890));
// 输出: "1,234,567,890"

console.log(formatter.format(9876543210));
// 输出: "9,876,543,210"

格式化器会在每三个数字的间隔处插入分隔符,使得即使是十亿级别的数字也能轻松阅读。这种自动分组适用于任何大小的数字,无需您手动计算分隔符位置。

复用格式化器以提高性能

创建一个新的 Intl.NumberFormat 实例需要加载区域设置数据并处理选项。当需要使用相同的区域设置和设置格式化多个数字时,可以创建一次格式化器并重复使用。

const formatter = new Intl.NumberFormat('en-US');

const numbers = [1234, 5678, 91011, 121314];

numbers.forEach(number => {
  console.log(formatter.format(number));
});
// 输出:
// "1,234"
// "5,678"
// "91,011"
// "121,314"

这种方法比为每个数字创建一个新的格式化器更高效。当格式化包含数百或数千个值的数组时,性能差异会变得显著。

在模板中格式化数字

您可以在任何向用户显示数字的地方使用 Intl.NumberFormat。这包括将格式化的数字插入到 HTML 模板中、在表格中显示值或在仪表板中显示统计数据。

const formatter = new Intl.NumberFormat(navigator.language);

const totalUsers = 1234567;
const activeUsers = 891234;

document.getElementById('total-users').textContent = formatter.format(totalUsers);
document.getElementById('active-users').textContent = formatter.format(activeUsers);

格式化后的字符串与其他字符串值一样。您可以将它们插入到文本内容、属性或任何其他显示信息的上下文中。