Как форматировать числа с точностью до 2 десятичных знаков в JavaScript
Отображение чисел с точностью до 2 десятичных знаков для цен, процентов и измерений
Введение
Многие приложения должны отображать числа с фиксированным количеством десятичных знаков. Цены обычно показываются с двумя десятичными знаками, например, $19.99. Проценты часто отображаются как 45.50%. Измерения используют одинаковое количество десятичных знаков для удобства чтения, например, 3.14 метра.
Контроль за количеством десятичных знаков обеспечивает визуальную согласованность в вашем приложении. Без явного форматирования JavaScript отображает числа с разным количеством десятичных знаков в зависимости от их фактического значения. Число 5 отображается как "5", а 5.5 как "5.5", создавая несогласованность в выравнивании и внешнем виде.
Этот урок показывает, как форматировать числа с точностью до 2 десятичных знаков или до 2 десятичных знаков таким образом, чтобы учитывать различные языковые и региональные стандарты.
Использование toFixed() для базового форматирования
Метод toFixed() преобразует число в строку с указанным количеством десятичных знаков. Передайте количество десятичных знаков в качестве аргумента.
const price = 19.9;
const formatted = price.toFixed(2);
console.log(formatted);
// Вывод: "19.90"
Метод всегда отображает ровно 2 десятичных знака. Если у числа меньше десятичных знаков, toFixed() добавляет нули. Если больше, метод округляет до 2 знаков.
const examples = [5, 5.5, 5.555, 5.999];
examples.forEach(num => {
console.log(num.toFixed(2));
});
// Вывод:
// "5.00"
// "5.50"
// "5.56"
// "6.00"
Метод toFixed() возвращает строку, а не число. Это сделано намеренно, так как завершающие нули имеют значение для отображения, но будут потеряны, если вернуть число.
Проблема локализации с toFixed()
Метод toFixed() всегда использует точку в качестве разделителя десятичных знаков, независимо от локали пользователя. Во многих странах вместо точки используется запятая как разделитель десятичных знаков.
const price = 19.99;
console.log(price.toFixed(2));
// Вывод: "19.99" (всегда используется точка)
Для пользователей из Германии, Франции, Испании и многих других стран это выглядит неправильно. Они ожидают увидеть "19,99" вместо "19.99". Метод toFixed() не может создавать вывод, соответствующий локали.
Чтобы правильно форматировать числа для разных локалей, используйте API Intl.NumberFormat.
Использование Intl.NumberFormat для форматирования с учетом локали
Intl.NumberFormat API форматирует числа в соответствии с конвенциями локали. Создайте форматировщик с указанием локали и опций, затем вызовите его метод format() с числом.
const formatter = new Intl.NumberFormat("de-DE", {
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
const price = 19.99;
console.log(formatter.format(price));
// Вывод: "19,99" (используется запятая для немецкой локали)
Один и тот же форматировщик выдает разные результаты для разных локалей.
const price = 19.99;
const usFormatter = new Intl.NumberFormat("en-US", {
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
const deFormatter = new Intl.NumberFormat("de-DE", {
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
console.log(usFormatter.format(price));
// Вывод: "19.99"
console.log(deFormatter.format(price));
// Вывод: "19,99"
Десятичный разделитель автоматически меняется в зависимости от локали.
Форматирование с точностью до 2 десятичных знаков
Чтобы отображать ровно 2 десятичных знака, установите minimumFractionDigits и maximumFractionDigits равными 2. Это гарантирует, что вывод всегда будет содержать 2 десятичных знака, добавляя нули при необходимости и округляя, если число имеет большую точность.
const formatter = new Intl.NumberFormat("en-US", {
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
console.log(formatter.format(5));
// Вывод: "5.00"
console.log(formatter.format(5.5));
// Вывод: "5.50"
console.log(formatter.format(5.555));
// Вывод: "5.56"
Опция minimumFractionDigits управляет добавлением нулей. Без нее числа с меньшим количеством десятичных знаков не будут показывать нули.
const withoutMinimum = new Intl.NumberFormat("en-US", {
maximumFractionDigits: 2
});
console.log(withoutMinimum.format(5));
// Вывод: "5"
const withMinimum = new Intl.NumberFormat("en-US", {
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
console.log(withMinimum.format(5));
// Вывод: "5.00"
Установка обеих опций на одно значение гарантирует одинаковое количество десятичных знаков для всех чисел.
Форматирование с максимумом в 2 десятичных знака
Иногда требуется отображать десятичные знаки только при необходимости, с максимумом в 2. Установите maximumFractionDigits равным 2, а minimumFractionDigits равным 0 или просто опустите его.
const formatter = new Intl.NumberFormat("en-US", {
minimumFractionDigits: 0,
maximumFractionDigits: 2
});
console.log(formatter.format(5));
// Вывод: "5"
console.log(formatter.format(5.5));
// Вывод: "5.5"
console.log(formatter.format(5.555));
// Вывод: "5.56"
Этот подход удаляет конечные нули, но при этом ограничивает точность до 2 десятичных знаков. Он хорошо подходит для отображения измерений или статистики, где конечные нули не несут дополнительной информации.
Значение по умолчанию для minimumFractionDigits равно 0 для простого форматирования чисел, поэтому его можно опустить.
const formatter = new Intl.NumberFormat("en-US", {
maximumFractionDigits: 2
});
console.log(formatter.format(5));
// Вывод: "5"
console.log(formatter.format(5.5));
// Вывод: "5.5"
Повторное использование форматтеров для повышения производительности
Создание нового экземпляра Intl.NumberFormat является относительно затратной операцией. Если вы форматируете много чисел с одинаковыми параметрами, создайте форматтер один раз и используйте его повторно.
const formatter = new Intl.NumberFormat("en-US", {
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
const prices = [19.99, 29.5, 99, 149.999];
prices.forEach(price => {
console.log(formatter.format(price));
});
// Результат:
// "19.99"
// "29.50"
// "99.00"
// "150.00"
Этот подход более эффективен, чем создание нового форматтера для каждого числа.
Когда использовать каждый подход
Используйте ровно 2 десятичных знака при отображении цен, денежных сумм или любых значений, где десятичные знаки имеют семантическое значение. Отображение "$5.00" вместо "$5" указывает на точность и соответствует ожиданиям пользователей для цен.
Используйте до 2 десятичных знаков при отображении статистики, измерений или вычисленных значений, где конечные нули не добавляют информации. Отображение "5 метров" вместо "5.00 метров" выглядит чище и удобочитаемее.
Используйте toFixed() только в том случае, если вы уверены, что все ваши пользователи используют одну и ту же систему десятичных разделителей, или если результат не предназначен для отображения пользователю. Для интернационализированных приложений предпочтительнее использовать Intl.NumberFormat.
Использование предпочтительного языка пользователя
Вместо жесткого указания локали используйте языковые предпочтения браузера пользователя. Свойство navigator.language предоставляет предпочтительную локаль пользователя.
const formatter = new Intl.NumberFormat(navigator.language, {
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
const price = 19.99;
console.log(formatter.format(price));
// Результат зависит от локали пользователя
// Для en-US: "19.99"
// Для de-DE: "19,99"
// Для fr-FR: "19,99"
Вы также можете передать весь массив navigator.languages, чтобы API Intl выбрал первую поддерживаемую локаль из предпочтений пользователя.
const formatter = new Intl.NumberFormat(navigator.languages, {
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
Этот подход обеспечивает автоматический резервный вариант, если первый предпочтительный язык пользователя не поддерживается.