如何为正数显示加号

使用 signDisplay 选项在 JavaScript 格式化数字时显式显示加号

简介

当你在天气应用中显示数字 5 作为温度变化时,用户无法判断这是 5 度的绝对温度,还是增加了 5 度的变化。缺少加号会造成歧义。通过将加号明确显示为 +5,可以清楚地传达该数值表示的是上升,而不是中性测量。

在展示变化、差异或增减值(delta)时,这种区分非常重要。股票价格变动、账户余额调整、分数差异和温度变化等场景,都需要明确的正负号来指示变化方向。JavaScript 的 Intl.NumberFormat 提供了 signDisplay 选项,用于控制正负号的显示时机。

数字的默认显示方式

默认情况下,JavaScript 只会为负数显示负号。正数和零则不会显示任何符号。

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

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

console.log(formatter.format(-42));
// Output: "-42"

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

这种默认行为适用于价格、数量或测量值等绝对数值。但当你需要显示变化或差异时,缺少加号会让正数的含义变得模糊。

以显示每日温度变化为例。如果没有明确的符号,用户看到 3 和 5 这样的数字时,可能会误以为是绝对温度,而不是变化值。使用 +3 和 +5 这样的明确符号,含义就非常清晰。

使用 signDisplay 显示加号

Intl.NumberFormat 中的 signDisplay 选项用于控制数字符号的显示时机。将 signDisplay 设置为 "always" 时,正负号都会显示。

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

console.log(formatter.format(42));
// Output: "+42"

console.log(formatter.format(-42));
// Output: "-42"

console.log(formatter.format(0));
// Output: "+0"

现在,正数会显示加号,负数会显示减号,零也会显示加号。这种格式适用于需要通过符号表达含义的变化值展示。

了解所有 signDisplay 的取值

signDisplay 选项支持五种取值。每种取值都针对正数、负数和零的符号显示有不同的用途。

auto 值:默认符号行为

"auto" 是默认行为。它会为负数(包括负零)显示减号,正数和正零则不显示符号。

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

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

console.log(formatter.format(-100));
// Output: "-100"

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

当展示绝对值且无符号即表示正数时,建议使用 "auto"。这是价格、计数和测量等标准格式。

always 值:显示所有符号

"always" 取值会为所有数字(包括正数、负数和零)显示符号。

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

console.log(formatter.format(100));
// Output: "+100"

console.log(formatter.format(-100));
// Output: "-100"

console.log(formatter.format(0));
// Output: "+0"

当展示变化或增减值(delta),且零表示无变化时,建议使用 "always"。零上的加号可以明确表示零是中性值,而不是缺失值。

exceptZero 值:隐藏零的符号

"exceptZero" 取值会为正数和负数显示符号,但零不显示符号。

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

console.log(formatter.format(100));
// Output: "+100"

console.log(formatter.format(-100));
// Output: "-100"

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

当零代表一种特殊状态,需要与正负值在视觉上区分时,建议使用 "exceptZero"。例如,显示分数变化时,零表示未发生变化。

negative 值:仅显示减号

"negative" 值仅为负数显示减号(不包括负零),正数和零不显示符号。

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

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

console.log(formatter.format(-100));
// Output: "-100"

console.log(formatter.format(-0));
// Output: "0"

当你需要突出显示负值,而将正值和零视为中性时,使用 "negative"。这适用于账户余额等场景,负值代表欠款。

never:隐藏所有符号

"never" 值会让所有数字都不显示符号,即使是负数也不例外。

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

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

console.log(formatter.format(-100));
// Output: "100"

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

当你需要显示数字的绝对值而不考虑其符号时,使用 "never"。这适用于数值方向已通过颜色或图标等方式表达的场景。

何时使用各 signDisplay 选项

根据数字所代表的含义以及用户的解读需求,选择 signDisplay 值。

对于变化、差异或增量等需要通过符号指示方向的场景,使用 "always"。温度变化、股价波动和分数差异等都需要明确的符号来表示数值的增减。

对于零表示无变化且应视觉上中性的场景,使用 "exceptZero"。这样可以让零作为既非增加也非减少的特殊情况突出显示。

当数字表示数量或测量值而非变化时,使用 "auto" 来显示绝对值。价格、距离、重量和计数等都适合使用默认符号显示。

当负数需要特别关注而正数为常规情况时,使用 "negative"。账户余额和利润计算等场景通常会突出显示负债,而正余额则视为标准。

当数值的方向已通过其他方式(如颜色或图标)表达时,建议使用 "never" 来显示绝对值。这样可以避免符号信息的冗余。

货币显示加号

货币格式化可与 signDisplay 配合使用,明确展示账户变动和交易金额的正负符号。

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

console.log(formatter.format(250.50));
// Output: "+$250.50"

console.log(formatter.format(-75.25));
// Output: "-$75.25"

console.log(formatter.format(0));
// Output: "+$0.00"

这种格式可以清晰地显示一笔交易是增加还是减少了账户资金。加号让存款变得明确,而不是仅仅隐含。

你可以将货币格式化与 exceptZero 结合,区分无变化、正向和负向交易。

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

console.log(formatter.format(250.50));
// Output: "+$250.50"

console.log(formatter.format(-75.25));
// Output: "-$75.25"

console.log(formatter.format(0));
// Output: "$0.00"

现在零值不带符号,能在视觉上与实际盈亏区分开。

百分比显示加号

百分比变化通常需要显式符号,以显示数值是增加还是减少。

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

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

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

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

这种格式适用于显示增长率、利率或业绩变化。加号明确表示正增长,而不是让用户自行推断。

在零值有特殊含义的场景下显示百分比变化时,建议使用 exceptZero 使零值视觉上保持中性。

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

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

console.log(formatter.format(0));
// Output: "0.0%"

不带符号的零值清楚地表示没有发生变化。

signDisplay 与小数位数结合使用

signDisplay 选项可与所有其他数字格式化选项配合使用。你可以同时控制小数位数、四舍五入和千位分隔符,并灵活设置符号显示。

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

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

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

这种组合确保了小数位数一致,同时对正负数值都显式显示符号。

你还可以将 signDisplay 与紧凑表示法结合,用于显示大幅变动。

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

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

console.log(formatter.format(-850000));
// Output: "-850K"

紧凑格式让大数值更易读,同时符号显示变动方向。

重点回顾

signDisplay 选项在 Intl.NumberFormat 中用于控制格式化数字时正负号的显示时机。将 signDisplay 设为 "always" 可对所有数字显示符号,设为 "exceptZero" 可隐藏零的符号,设为 "auto" 为默认行为,设为 "negative" 仅显示负号,设为 "never" 则全部隐藏符号。

请根据数值是否表示变动或绝对值,以及零是否需要特殊视觉处理,选择合适的 signDisplay 值。可将 signDisplay 与货币、百分比、小数位等其他格式化选项结合,满足应用的精确格式需求。