Положительные и отрицательные числа

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

В разных странах отрицательные значения отображаются по-разному:

  • -1234.56
  • −1 234,56
  • (1,234.56)
  • 1 234,56-

Globalize использует данные стандарта CLDR и автоматически учитывает локальные правила отображения знаков числа.


Форматирование положительных чисел

Базовое форматирование

Globalize.locale("en");

const formatter = Globalize.numberFormatter();

console.log(formatter(1250));
// 1,250

Для английской локали разделителем тысяч является запятая.


Русская локаль

Globalize.locale("ru");

const formatter = Globalize.numberFormatter();

console.log(formatter(1250));
// 1 250

В русской локали:

  • используется пробел как разделитель тысяч;
  • десятичный разделитель — запятая.

Форматирование дробных положительных чисел

Globalize.locale("ru");

const formatter = Globalize.numberFormatter({
    minimumFractionDigits: 2
});

console.log(formatter(1234.5));
// 1 234,50

Параметр minimumFractionDigits задаёт минимальное количество цифр после запятой.


Форматирование отрицательных чисел

Стандартный отрицательный формат

Globalize.locale("en");

const formatter = Globalize.numberFormatter();

console.log(formatter(-1500));
// -1,500

Для большинства локалей отрицательное число отображается со знаком минус перед числом.


Отрицательные дробные значения

Globalize.locale("ru");

const formatter = Globalize.numberFormatter({
    minimumFractionDigits: 2
});

console.log(formatter(-99.5));
// -99,50

Globalize автоматически:

  • сохраняет знак минус;
  • форматирует дробную часть по правилам локали.

Особенности локалей

Различия между странами

Английская локаль

Globalize.locale("en");

const formatter = Globalize.numberFormatter();

console.log(formatter(-1234567.89));
// -1,234,567.89

Немецкая локаль

Globalize.locale("de");

const formatter = Globalize.numberFormatter();

console.log(formatter(-1234567.89));
// -1.234.567,89

Французская локаль

Globalize.locale("fr");

const formatter = Globalize.numberFormatter();

console.log(formatter(-1234567.89));
// -1 234 567,89

Отличия касаются:

  • разделителей тысяч;
  • десятичного разделителя;
  • символов пробела;
  • положения минуса.

Использование шаблонов чисел

Globalize поддерживает разные стили отображения чисел.

Проценты

Globalize.locale("en");

const formatter = Globalize.numberFormatter({
    style: "percent"
});

console.log(formatter(-0.25));
// -25%

Денежные значения

Globalize.locale("ru");

const formatter = Globalize.numberFormatter({
    style: "currency",
    currency: "RUB"
});

console.log(formatter(-1500));
// -1 500,00 ₽

Для валют Globalize автоматически:

  • подставляет символ валюты;
  • форматирует дробную часть;
  • правильно отображает отрицательное значение.

Парсинг положительных и отрицательных чисел

Форматирование — не единственная задача. Часто требуется преобразовать строку обратно в число.

Парсинг положительного числа

Globalize.locale("ru");

const parser = Globalize.numberParser();

console.log(parser("1 250"));
// 1250

Парсинг отрицательного числа

Globalize.locale("ru");

const parser = Globalize.numberParser();

console.log(parser("-1 250,75"));
// -1250.75

Globalize корректно:

  • распознаёт знак минус;
  • учитывает локальные разделители;
  • преобразует строку в Number.

Проверка знака числа

После парсинга можно определить тип значения.

Проверка на отрицательное число

const value = parser("-500");

if (value < 0) {
    console.log("Отрицательное число");
}

Проверка на положительное число

const value = parser("500");

if (value > 0) {
    console.log("Положительное число");
}

Проверка на ноль

const value = parser("0");

if (value === 0) {
    console.log("Ноль");
}

Работа с пользовательскими форматами

Форматирование со знаком плюс

По умолчанию положительные числа отображаются без знака +.

Пользовательский формат позволяет изменить поведение:

const formatter = Globalize.numberFormatter({
    pattern: "+#,##0;-#,##0"
});

console.log(formatter(100));
// +100

console.log(formatter(-100));
// -100

Использование скобок для отрицательных чисел

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

const formatter = Globalize.numberFormatter({
    pattern: "#,##0;(#,##0)"
});

console.log(formatter(-5000));
// (5,000)

Положительные и отрицательные проценты

Globalize.locale("en");

const formatter = Globalize.numberFormatter({
    style: "percent",
    minimumFractionDigits: 1
});

console.log(formatter(0.156));
// 15.6%

console.log(formatter(-0.156));
// -15.6%

Форматирование больших отрицательных чисел

Globalize.locale("en");

const formatter = Globalize.numberFormatter();

console.log(formatter(-9876543210));
// -9,876,543,210

Globalize автоматически добавляет разделители разрядов независимо от знака числа.


Научная запись

Положительные значения

const formatter = Globalize.numberFormatter({
    pattern: "0.###E0"
});

console.log(formatter(125000));
// 1.25E5

Отрицательные значения

console.log(formatter(-125000));
// -1.25E5

Работа с очень маленькими числами

const formatter = Globalize.numberFormatter({
    minimumFractionDigits: 5
});

console.log(formatter(-0.00012));
// -0.00012

Такие значения особенно важны:

  • в финансовых системах;
  • научных расчётах;
  • аналитике;
  • статистике.

Автоматическое определение локали

const locale = navigator.language;

Globalize.locale(locale);

const formatter = Globalize.numberFormatter();

console.log(formatter(-1500.5));

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


Комбинирование с Intl

Globalize часто используется совместно с API Intl.

const number = -1250.75;

const intlResult = new Intl.NumberFormat("ru-RU").format(number);

console.log(intlResult);
// -1 250,75

Однако Globalize предоставляет:

  • более гибкие шаблоны;
  • поддержку CLDR;
  • расширенную настройку локалей;
  • дополнительные возможности парсинга.

Ошибки при работе с отрицательными числами

Неправильный разделитель

parser("1,250");

Для русской локали такая строка может быть обработана некорректно, поскольку ожидается другой формат.


Смешивание локалей

Globalize.locale("ru");

parser("1,234.56");

Строка соответствует английской локали, а не русской.


Отсутствие данных CLDR

Перед использованием локали необходимо загрузить соответствующие данные:

Globalize.load(cldrData);
Globalize.locale("ru");

Без CLDR форматирование работать не будет.


Практический пример: банковский баланс

Globalize.locale("ru");

const currencyFormatter = Globalize.numberFormatter({
    style: "currency",
    currency: "RUB"
});

const balance1 = 15000;
const balance2 = -3400;

console.log(currencyFormatter(balance1));
// 15 000,00 ₽

console.log(currencyFormatter(balance2));
// -3 400,00 ₽

Положительный баланс отображается стандартно, отрицательный — со знаком минус.


Практический пример: анализ прибыли и убытков

const formatter = Globalize.numberFormatter({
    pattern: "+#,##0;-#,##0"
});

const values = [5000, -1200, 3500, -800];

values.forEach(value => {
    console.log(formatter(value));
});

Результат:

+5,000
-1,200
+3,500
-800

Такой формат удобен для:

  • финансовых отчётов;
  • аналитических панелей;
  • систем мониторинга;
  • таблиц прибыли и убытков.

Производительность форматирования

Создание форматтера — сравнительно дорогая операция.

Неправильный подход

numbers.forEach(number => {
    const formatter = Globalize.numberFormatter();
    console.log(formatter(number));
});

Правильный подход

const formatter = Globalize.numberFormatter();

numbers.forEach(number => {
    console.log(formatter(number));
});

Форматтер создаётся один раз и переиспользуется.


Форматирование отрицательного нуля

В JavaScript существует значение -0.

console.log(-0);

Globalize может отображать его как отрицательное число:

const formatter = Globalize.numberFormatter();

console.log(formatter(-0));
// -0

Проверка:

Object.is(-0, 0);
// false

Сравнение чисел после парсинга

const parser = Globalize.numberParser();

const a = parser("-10");
const b = parser("10");

console.log(a < b);
// true

После парсинга значения становятся обычными числами JavaScript и участвуют в математических операциях без ограничений.


Использование чисел в интерфейсах

Положительные и отрицательные значения часто используются:

  • в банковских приложениях;
  • в системах учёта;
  • в интернет-магазинах;
  • в аналитических сервисах;
  • в графиках;
  • в отчётности;
  • в CRM-системах;
  • в ERP-платформах.

Корректное локализованное отображение чисел влияет:

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