如何使用百分号格式化百分比

使用 Intl.NumberFormat 的百分比样式,以符合本地化格式将数字显示为百分比

介绍

百分比在许多应用中都会出现,从显示完成进度到展示利率和折扣金额。一个简单的方法是将数字与百分号连接起来,这在基本情况下可以使用,但无法考虑不同语言和地区如何格式化百分比。在土耳其语中,百分号出现在数字前面,如 %50。在法语中,数字与百分号之间有一个空格,如 50 %。阿拉伯语使用特殊的百分号字符,而不是标准的 % 符号。

JavaScript 的 Intl.NumberFormat API 可以自动处理这些格式化差异。通过将 style 选项设置为 "percent",您可以为任何区域设置获得正确格式化的百分比,而无需编写特定于区域的代码。

为什么百分比格式因语言区域而异

百分号的位置和间距规则因语言区域而异。英语将百分号直接放在数字后面且没有空格。法语在百分号前添加一个空格。土耳其语将百分号放在数字前面。这些差异反映了每种语言的自然阅读习惯和约定。

格式化差异不仅仅体现在符号位置上。一些语言区域使用不同的字符作为百分号。例如,阿拉伯语使用 ٪ (U+066A) 而不是 ASCII 百分号。小数点分隔符和千位分隔符也因语言区域而异,就像常规数字格式一样。

当您通过字符串连接硬编码百分比格式时,您会强制所有用户看到单一语言区域的格式。例如,法语用户看到 50% 而不是 50 % 会感到不自然。土耳其语用户看到 50% 而不是 %50 也会遇到同样的问题。Intl API 通过为每个语言区域应用正确的格式化规则解决了这个问题。

将数字格式化为百分比

Intl.NumberFormat 中的 style 选项控制数字是格式化为普通数字、货币、百分比还是单位。将 style 设置为 "percent" 以将数字格式化为百分比。

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

console.log(formatter.format(0.75));
// 输出: "75%"

console.log(formatter.format(0.05));
// 输出: "5%"

console.log(formatter.format(1.5));
// 输出: "150%"

格式化器会自动将输入值乘以 100 并附加百分号。这意味着您需要将小数值传递给格式化器。例如,值 0.75 会变成 75%,值 1.5 会变成 150%。

这种小数输入的约定与数学和大多数编程计算中百分比的工作方式一致。当您计算增长率或完成率等百分比时,结果通常是介于 0 和 1 之间的小数值。您可以直接将此值传递给格式化器,而无需先将其转换为百分比。

理解小数输入值

百分比格式化器期望小数输入,其中 1.0 表示 100%。这种设计选择与代码中百分比的计算方式相匹配。

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

// 计算完成百分比
const completed = 75;
const total = 100;
const ratio = completed / total;

console.log(formatter.format(ratio));
// 输出: "75%"

// 计算增长率
const oldValue = 1000;
const newValue = 1250;
const growth = (newValue - oldValue) / oldValue;

console.log(formatter.format(growth));
// 输出: "25%"

当您将完成值除以总值时,结果是 0.75。直接将其传递给格式化器,它会显示为 75%。当您计算增长率(即变化量与原始值的比率)时,结果是 0.25。格式化器会将其显示为 25%。

这种方法可以防止一个常见错误,即开发人员在格式化之前将值乘以 100,导致结果变成 7500% 而不是 75%。格式化器会处理乘法,因此您可以在代码中使用自然的小数表示。

处理超出 0-1 范围的值

百分比不限于 0% 到 100% 之间的值。小于零的值表示负百分比。大于 1.0 的值表示超过 100% 的百分比。

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

console.log(formatter.format(-0.15));
// 输出: "-15%"

console.log(formatter.format(2.5));
// 输出: "250%"

console.log(formatter.format(0.0025));
// 输出: "0%"

负值会以负号格式化。这对于显示减少、损失或负增长率非常有用。大于 1.0 的值会格式化为超过 100% 的百分比,这在显示同比增长或新值超过基准值的比较时很常见。

由于默认的精度设置,非常小的值可能会四舍五入为 0%。例如,值 0.0025(表示 0.25%)会显示为 0%,因为百分比的默认最大小数位数为 0。下一课将介绍如何控制小数位数以准确显示这些较小的百分比。

在不同语言环境中格式化百分比

百分比格式会根据您指定的语言环境进行调整。每种语言环境对符号位置、间距和符号都有自己的规则。

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

console.log(enFormatter.format(0.5));
// 输出: "50%"

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

console.log(frFormatter.format(0.5));
// 输出: "50 %"

const trFormatter = new Intl.NumberFormat("tr-TR", {
  style: "percent"
});

console.log(trFormatter.format(0.5));
// 输出: "%50"

const arFormatter = new Intl.NumberFormat("ar-SA", {
  style: "percent"
});

console.log(arFormatter.format(0.5));
// 输出: "٪50"

英语将百分号直接放在数字后面。法语在百分号前添加一个空格。土耳其语将百分号放在数字前面。阿拉伯语使用阿拉伯百分号并遵循从右到左的文本方向。

这些差异会根据语言环境参数自动处理。您无需编写条件逻辑来处理不同的语言环境。只需使用用户的语言环境创建格式化器,它就会为该语言环境生成正确的输出。

控制百分比的小数位数

默认情况下,百分比格式化不显示小数位。例如,值 0.755 在四舍五入后格式化为 76%。您可以使用 minimumFractionDigitsmaximumFractionDigits 选项来控制小数位数。

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

console.log(defaultFormatter.format(0.755));
// 输出: "76%"

const oneDecimalFormatter = new Intl.NumberFormat("en-US", {
  style: "percent",
  minimumFractionDigits: 1,
  maximumFractionDigits: 1
});

console.log(oneDecimalFormatter.format(0.755));
// 输出: "75.5%"

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

console.log(twoDecimalFormatter.format(0.755));
// 输出: "75.50%"

minimumFractionDigits 选项确保格式化器至少显示指定数量的小数位,必要时会添加尾随零。而 maximumFractionDigits 选项限制小数位数,必要时会对值进行四舍五入。

将两者设置为相同的值可以确保所有百分比的格式一致。这在表格和图表中非常有用,因为您希望所有百分比在视觉上对齐。

下一课将更深入地讲解小数位控制,包括如何处理尾随零以及准确显示非常小的百分比。

将百分比与符号显示相结合

百分比格式化可以与 signDisplay 选项结合使用,以明确显示正百分比的加号。这在显示变化或增长率时非常有用,因为符号可以指示方向。

const formatter = new Intl.NumberFormat("en-US", {
  style: "percent",
  signDisplay: "always",
  minimumFractionDigits: 1,
  maximumFractionDigits: 1
});

console.log(formatter.format(0.0523));
// 输出: "+5.2%"

console.log(formatter.format(-0.0341));
// 输出: "-3.4%"

console.log(formatter.format(0));
// 输出: "+0.0%"

signDisplay 选项在之前的课程中已经介绍过。当与百分比格式化结合使用时,它可以明确表示百分比是增加还是减少。如果没有明确的加号,在同时显示增益和损失的上下文中,正百分比可能会引起歧义。

将零格式化为百分比

零默认格式化为 0%。如何处理零取决于零是表示无变化、无值还是有意义的测量值。

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

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

const withSignFormatter = new Intl.NumberFormat("en-US", {
  style: "percent",
  signDisplay: "exceptZero"
});

console.log(withSignFormatter.format(0.05));
// 输出: "+5%"

console.log(withSignFormatter.format(0));
// 输出: "0%"

使用 signDisplay: "exceptZero" 会为正百分比和负百分比显示符号,但对零省略符号。当零表示中性状态(如无变化)时,这使零在视觉上更为显著。

何时使用百分比格式化

在显示自然以百分比表示的比率、速率或比例时,使用百分比格式化。常见的使用场景包括完成进度、利率、折扣金额、增长率、成功率和概率值。

当需要百分号在特定位置显示以保持视觉一致性时,不要使用百分比格式化。如果设计要求百分号始终显示在右侧,请使用字符串拼接。然而,这会牺牲国际化的正确性。

此外,当处理已经乘以 100 的值时,也应避免使用百分比格式化。如果数据以整数形式存储百分比(例如 75 表示 75%),在格式化之前将其除以 100,或者使用普通数字格式化并手动附加百分号。

理解百分比格式化器的精度

百分比格式化的默认精度为 0 位小数。这与普通数字格式化不同,后者会根据输入值调整精度。百分比格式化器会将值四舍五入为整百分比,除非您明确设置小数位选项。

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

console.log(formatter.format(0.755));
// 输出: "76%"

console.log(formatter.format(0.754));
// 输出: "75%"

console.log(formatter.format(0.001));
// 输出: "0%"

值会四舍五入到最接近的整百分比。值 0.755 四舍五入为 76%。值 0.754 四舍五入为 75%。像 0.001 这样非常小的值会四舍五入为 0%。

如果需要显示小百分比或分数百分比,请增加最大小数位数。下一课将详细介绍精度控制。