Как показать или скрыть знак минус для отрицательных чисел?

Управляйте отображением знаков отрицательных и положительных чисел в форматированных числах для разных контекстов

Введение

Разные контексты требуют разных способов представления отрицательных чисел. На панели, показывающей изменения температуры, нужны явные знаки плюс и минус, чтобы указать направление. На графике, отображающем величины, важны только абсолютные значения, и знак следует полностью скрыть. Финансовые отчеты следуют бухгалтерским стандартам, где отрицательные суммы заключаются в скобки вместо использования знаков минус.

API Intl.NumberFormat в JavaScript предоставляет опцию signDisplay, которая позволяет управлять отображением знаков в форматированных числах. Эта опция дает вам точный контроль над видимостью знаков для отрицательных чисел, положительных чисел и нуля.

Как JavaScript по умолчанию форматирует отрицательные числа

По умолчанию Intl.NumberFormat показывает знак минус для отрицательных чисел и не показывает знак для положительных чисел.

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

formatter.format(-42);
// "-42"

formatter.format(42);
// "42"

formatter.format(0);
// "0"

Такое поведение по умолчанию подходит для большинства случаев, но вы можете изменить его, если ваш случай использования требует другого подхода к отображению знаков.

Управление отображением знаков с помощью опции signDisplay

Опция signDisplay принимает пять значений, которые определяют, когда отображаются знаки:

  • "auto": Показывать знаки только для отрицательных чисел, включая отрицательный ноль (по умолчанию)
  • "never": Никогда не показывать знаки
  • "always": Всегда показывать знаки как для положительных, так и для отрицательных чисел
  • "exceptZero": Показывать знаки для положительных и отрицательных чисел, но не для нуля
  • "negative": Показывать знаки только для отрицательных чисел, исключая отрицательный ноль

Передайте опцию signDisplay в объекте настроек при создании форматтера.

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

Полное скрытие знака минус

Используйте signDisplay: 'never', чтобы скрыть все знаки и отображать только абсолютные значения.

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

formatter.format(-100);
// "100"

formatter.format(100);
// "100"

formatter.format(-0);
// "0"

Эта настройка удаляет знак из всех чисел, делая форматирование -100 и 100 идентичным. Отрицательный ноль форматируется как "0" без знака.

Используйте эту опцию при отображении величин, где направление не имеет значения, например, для абсолютных изменений в визуализациях данных, расчетах расстояний или погрешностях.

const changes = [-15, 23, -8, 42];

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

changes.map(change => formatter.format(change));
// ["15", "23", "8", "42"]

Показывать знак минус только для отрицательных чисел

signDisplay: 'auto' — это поведение по умолчанию. Оно отображает знаки для отрицательных чисел, но не для положительных.

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

formatter.format(-100);
// "-100"

formatter.format(100);
// "100"

formatter.format(-0);
// "-0"

Обратите внимание, что отрицательный ноль отображается как "-0" с этой опцией. JavaScript различает положительный и отрицательный ноль, что может возникать в некоторых математических операциях.

Используйте signDisplay: 'negative', чтобы скрыть знак для отрицательного нуля, сохраняя его для других отрицательных чисел.

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

formatter.format(-100);
// "-100"

formatter.format(100);
// "100"

formatter.format(-0);
// "0"

Опция negative рассматривает отрицательный ноль как особый случай и форматирует его без знака. Это предотвращает путаницу в тех случаях, когда различие между положительным и отрицательным нулем не имеет значения для пользователей.

Показывать знаки для всех чисел, кроме нуля

Используйте signDisplay: 'exceptZero', чтобы показывать знаки как для положительных, так и для отрицательных чисел, но опускать знак, если значение равно нулю.

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

formatter.format(-100);
// "-100"

formatter.format(100);
// "+100"

formatter.format(0);
// "0"

formatter.format(-0);
// "0"

Положительные числа отображаются с плюсом. Нулевые значения, будь то положительные или отрицательные, отображаются без знака.

Эта опция хорошо подходит для отображения изменений или дельт, где ноль означает отсутствие изменений. Отображение "+0" или "-0" может быть запутанным, но отображение "0" делает значение понятным.

const deltas = [5, -3, 0, -0, 12];

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

deltas.map(delta => formatter.format(delta));
// ["+5", "-3", "0", "0", "+12"]

Показывать знаки для всех чисел

Используйте signDisplay: 'always', чтобы показывать знаки для всех чисел, включая положительные числа и ноль.

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

formatter.format(-100);
// "-100"

formatter.format(100);
// "+100"

formatter.format(0);
// "+0"

formatter.format(-0);
// "-0"

Этот параметр добавляет знак плюса к положительным числам и положительному нулю. Отрицательный ноль сохраняет свой минус, что делает различие видимым.

Используйте эту опцию, когда нужно подчеркнуть направление для всех значений, например, изменения температуры, изменения высоты или финансовые прибыли и убытки.

const temperatures = [-5, 0, 3, -2];

const formatter = new Intl.NumberFormat('en-US', {
  style: 'unit',
  unit: 'celsius',
  signDisplay: 'always'
});

temperatures.map(temp => formatter.format(temp));
// ["-5°C", "+0°C", "+3°C", "-2°C"]

Комбинирование отображения знаков с форматированием валюты

Опция signDisplay работает со всеми стилями форматирования, включая форматирование валюты. В сочетании с currencySign: 'accounting' можно создавать форматы, соответствующие бухгалтерским стандартам.

const formatter = new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD',
  currencySign: 'accounting'
});

formatter.format(-1234.56);
// "($1,234.56)"

Бухгалтерская нотация заключает отрицательные суммы в скобки вместо использования знака минус. Эта конвенция делает отрицательные числа более заметными в финансовых отчетах.

Вы можете комбинировать бухгалтерскую нотацию с различными значениями signDisplay.

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

always.format(1234.56);
// "+$1,234.56"

always.format(-1234.56);
// "($1,234.56)"

const never = new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD',
  currencySign: 'accounting',
  signDisplay: 'never'
});

never.format(-1234.56);
// "$1,234.56"

С signDisplay: 'always' положительные суммы показывают знак плюса, а отрицательные суммы по-прежнему используют скобки. С signDisplay: 'never' как положительные, так и отрицательные суммы отображаются без знаков или скобок.

Когда использовать каждый вариант отображения знаков

Выбирайте значение signDisplay в зависимости от того, что представляют ваши числа и как пользователи их интерпретируют.

Используйте signDisplay: 'auto' для стандартного форматирования чисел, где отрицательные числа должны быть четко обозначены. Это значение по умолчанию, которое хорошо подходит для цен, подсчётов, измерений и большинства универсальных отображений чисел.

Используйте signDisplay: 'never', когда отображаете абсолютные значения или величины, где направление не имеет значения. Это подходит для расчётов расстояний, погрешностей, абсолютных изменений и визуализаций данных, показывающих величину без направления.

Используйте signDisplay: 'negative', если вам нужно стандартное форматирование отрицательных чисел, но вы хотите избежать отображения отрицательного нуля. Это предотвращает путаницу с отображением "-0" в математических или научных контекстах, где различие между положительным и отрицательным нулём не имеет значения для пользователей.

Используйте signDisplay: 'exceptZero', когда отображаете изменения или дельты, где ноль означает отсутствие изменений. Это делает приросты и убытки понятными, избегая путаницы с отображением "+0" или "-0". Изменения температуры, движения цен на акции и показатели производительности выигрывают от этого варианта.

Используйте signDisplay: 'always', когда направление имеет значение для всех значений, и вы хотите подчеркнуть как увеличения, так и уменьшения. Изменения температуры, различия в высоте и финансовые отчёты часто используют этот формат, чтобы сделать положительные и отрицательные значения одинаково явными.

// Стандартное ценообразование: используйте auto (по умолчанию)
new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD'
}).format(-50);
// "-$50.00"

// Абсолютная разница в цене: используйте never
new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD',
  signDisplay: 'never'
}).format(-50);
// "$50.00"

// Изменение цены: используйте exceptZero
new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD',
  signDisplay: 'exceptZero'
}).format(50);
// "+$50.00"

// Изменение температуры: используйте always
new Intl.NumberFormat('en-US', {
  style: 'unit',
  unit: 'celsius',
  signDisplay: 'always'
}).format(3);
// "+3°C"

Опция signDisplay предоставляет вам точный контроль над тем, как положительные и отрицательные числа отображаются в вашем приложении. Выбирайте значение, которое лучше всего передаёт смысл вашим пользователям в зависимости от контекста и цели каждого отображаемого числа.