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

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

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


Базовое форматирование дробных чисел

Для работы с форматированием необходимо подключить CLDR-данные и создать экземпляр Globalize.

const Globalize = require("globalize");

const globalize = new Globalize("en");

const formatter = globalize.numberFormatter();

console.log(formatter(1234.567));
// 1,234.567

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


Ограничение максимального количества десятичных знаков

Параметр maximumFractionDigits задаёт максимально допустимое число символов после десятичного разделителя.

const formatter = globalize.numberFormatter({
    maximumFractionDigits: 2
});

console.log(formatter(1234.5678));
// 1,234.57

Что происходит при форматировании

Число:

1234.5678

округляется до:

1234.57

Globalize автоматически применяет математическое округление.


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

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

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

console.log(formatter(15));
// 15.00

Это особенно важно:

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

Одновременное использование minimumFractionDigits и maximumFractionDigits

Обычно оба параметра используются вместе.

const formatter = globalize.numberFormatter({
    minimumFractionDigits: 2,
    maximumFractionDigits: 2
});

console.log(formatter(8));
// 8.00

console.log(formatter(8.1));
// 8.10

console.log(formatter(8.129));
// 8.13

Такой режим создаёт строго фиксированное количество десятичных знаков.


Форматирование валют

При работе с валютами количество десятичных знаков зависит от стандарта валюты.

const formatter = globalize.currencyFormatter("USD");

console.log(formatter(12.5));
// $12.50

Для японской иены дробная часть обычно отсутствует.

const formatter = globalize.currencyFormatter("JPY");

console.log(formatter(1200.75));
// ¥1,201

Globalize автоматически учитывает правила валюты через CLDR.


Переопределение количества дробных знаков у валют

Стандартное поведение можно изменить.

const formatter = globalize.currencyFormatter("USD", {
    minimumFractionDigits: 4,
    maximumFractionDigits: 4
});

console.log(formatter(15.2));
// $15.2000

Подобный подход используется:

  • в криптовалютных системах;
  • в финансовых терминалах;
  • в биржевых приложениях;
  • в системах расчёта процентов.

Округление чисел

Globalize использует стандартное округление.

const formatter = globalize.numberFormatter({
    maximumFractionDigits: 2
});

console.log(formatter(1.234));
// 1.23

console.log(formatter(1.235));
// 1.24

Принцип округления:

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

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

const formatter = globalize.numberFormatter({
    maximumFractionDigits: 6
});

console.log(formatter(0.000123456));
// 0.000123

Если значение содержит больше знаков, чем разрешено настройками, лишние цифры будут отброшены через округление.


Форматирование процентов

Проценты требуют особого внимания к дробной части.

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

console.log(formatter(0.256));
// 25.6%

Важно учитывать, что:

0.256

автоматически преобразуется в:

25.6%

Различия локалей

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

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

const globalize = new Globalize("en");

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

console.log(formatter(1234.5));
// 1,234.50

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

const globalize = new Globalize("de");

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

console.log(formatter(1234.5));
// 1.234,50

Особенности:

Локаль Разделитель тысяч Десятичный разделитель
en , .
de . ,
fr пробел ,

Подавление лишних нулей

Если задан только maximumFractionDigits, Globalize не будет дополнять число нулями.

const formatter = globalize.numberFormatter({
    maximumFractionDigits: 3
});

console.log(formatter(15));
// 15

console.log(formatter(15.2));
// 15.2

Такой формат полезен:

  • в аналитических панелях;
  • в графиках;
  • в научных вычислениях;
  • в статистических системах.

Форматирование научных данных

При выводе измерений и коэффициентов требуется высокая точность.

const formatter = globalize.numberFormatter({
    minimumFractionDigits: 5,
    maximumFractionDigits: 5
});

console.log(formatter(Math.PI));
// 3.14159

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


Динамическое управление точностью

Количество десятичных знаков можно изменять во время выполнения программы.

function createFormatter(precision) {
    return globalize.numberFormatter({
        minimumFractionDigits: precision,
        maximumFractionDigits: precision
    });
}

const formatter2 = createFormatter(2);
const formatter4 = createFormatter(4);

console.log(formatter2(10.56789));
// 10.57

console.log(formatter4(10.56789));
// 10.5679

Такой подход часто применяется:

  • в пользовательских настройках;
  • в инженерных системах;
  • в BI-панелях;
  • в приложениях визуализации данных.

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

Использование строк вместо чисел

formatter("12.345");

Хотя JavaScript способен выполнить преобразование, рекомендуется передавать именно числа.

Правильный вариант:

formatter(Number("12.345"));

Потеря точности JavaScript

Globalize не исправляет ограничения IEEE 754.

console.log(0.1 + 0.2);
// 0.30000000000000004

После форматирования:

const formatter = globalize.numberFormatter({
    maximumFractionDigits: 2
});

console.log(formatter(0.1 + 0.2));
// 0.3

Визуально проблема скрывается, но вычислительная ошибка остаётся.


Форматирование без дробной части

Для полного удаления десятичных знаков используется значение 0.

const formatter = globalize.numberFormatter({
    maximumFractionDigits: 0
});

console.log(formatter(15.9));
// 16

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

Globalize поддерживает альтернативный подход — управление значащими цифрами.

const formatter = globalize.numberFormatter({
    minimumSignificantDigits: 3,
    maximumSignificantDigits: 5
});

console.log(formatter(0.001234567));
// 0.0012346

Отличие от fractionDigits

Подход Что контролируется
fractionDigits знаки после запятой
significantDigits общая значимость числа

Комбинирование параметров

const formatter = globalize.numberFormatter({
    minimumFractionDigits: 2,
    maximumFractionDigits: 4,
    useGrouping: true
});

console.log(formatter(1234567.8));
// 1,234,567.80

Здесь одновременно используются:

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

Производительность

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

Нежелательный вариант:

for (const value of values) {
    const formatter = globalize.numberFormatter({
        maximumFractionDigits: 2
    });

    console.log(formatter(value));
}

Предпочтительный подход:

const formatter = globalize.numberFormatter({
    maximumFractionDigits: 2
});

for (const value of values) {
    console.log(formatter(value));
}

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


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

const priceFormatter = globalize.currencyFormatter("USD", {
    minimumFractionDigits: 2,
    maximumFractionDigits: 2
});

const prices = [10, 15.5, 22.789];

prices.forEach(price => {
    console.log(priceFormatter(price));
});

Результат:

$10.00
$15.50
$22.79

Практический пример: статистические данные

const statsFormatter = globalize.numberFormatter({
    maximumFractionDigits: 4
});

const values = [
    1.234567,
    9.876543,
    3.141592
];

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

Результат:

1.2346
9.8765
3.1416

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

function formatValue(value) {
    const digits = value < 1 ? 6 : 2;

    const formatter = globalize.numberFormatter({
        minimumFractionDigits: digits,
        maximumFractionDigits: digits
    });

    return formatter(value);
}

console.log(formatValue(15.2));
// 15.20

console.log(formatValue(0.000123));
// 0.000123

Подобная логика часто используется:

  • в финансовых приложениях;
  • в научных вычислениях;
  • при отображении коэффициентов;
  • в системах телеметрии.