Как отформатировать числа до 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);
// Output: "19.90"
Метод всегда показывает ровно 2 знака после запятой. Если у числа меньше знаков, toFixed() добавляет нули. Если больше — округляет до двух знаков.
const examples = [5, 5.5, 5.555, 5.999];
examples.forEach(num => {
console.log(num.toFixed(2));
});
// Output:
// "5.00"
// "5.50"
// "5.56"
// "6.00"
Метод toFixed() возвращает строку, а не число. Это сделано специально, потому что завершающие нули важны для отображения, но теряются, если вернуть число.
Проблема локализации с toFixed()
Метод toFixed() всегда использует точку в качестве разделителя дробной части, независимо от локали пользователя. Во многих странах в качестве разделителя используется запятая, а не точка.
const price = 19.99;
console.log(price.toFixed(2));
// Output: "19.99" (always uses period)
Для пользователей из Германии, Франции, Испании и многих других стран это выглядит неправильно. Они ожидают увидеть «19,99» вместо «19.99». Метод toFixed() не может выдать результат, соответствующий локали.
Чтобы правильно форматировать числа для разных локалей, используйте API Intl.NumberFormat.
Использование Intl.NumberFormat для форматирования с учётом локали
API Intl.NumberFormat форматирует числа по правилам выбранной локали. Создайте форматтер с нужной локалью и опциями, затем вызовите его метод format() с числом.
const formatter = new Intl.NumberFormat("de-DE", {
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
const price = 19.99;
console.log(formatter.format(price));
// Output: "19,99" (uses comma for German locale)
Один и тот же форматтер выдаёт разный результат для разных локалей.
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));
// Output: "19.99"
console.log(deFormatter.format(price));
// Output: "19,99"
Десятичный разделитель автоматически меняется в зависимости от локали.
Форматирование ровно с 2 знаками после запятой
Чтобы отображать ровно 2 знака после запятой, установите значения minimumFractionDigits и maximumFractionDigits равными 2. Это гарантирует, что результат всегда будет с двумя знаками после запятой: при необходимости добавляются нули, а при большем количестве знаков происходит округление.
const formatter = new Intl.NumberFormat("en-US", {
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
console.log(formatter.format(5));
// Output: "5.00"
console.log(formatter.format(5.5));
// Output: "5.50"
console.log(formatter.format(5.555));
// Output: "5.56"
Опция minimumFractionDigits отвечает за отображение завершающих нулей. Без неё числа с меньшим количеством знаков после запятой не будут показывать нули.
const withoutMinimum = new Intl.NumberFormat("en-US", {
maximumFractionDigits: 2
});
console.log(withoutMinimum.format(5));
// Output: "5"
const withMinimum = new Intl.NumberFormat("en-US", {
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
console.log(withMinimum.format(5));
// Output: "5.00"
Если оба параметра задать одинаковыми, количество знаков после запятой всегда будет одинаковым для всех чисел.
Форматирование с максимум 2 знаками после запятой
Иногда нужно показывать знаки после запятой только при необходимости, максимум до 2. Для этого установите maximumFractionDigits в 2, а minimumFractionDigits в 0 или просто не указывайте.
const formatter = new Intl.NumberFormat("en-US", {
minimumFractionDigits: 0,
maximumFractionDigits: 2
});
console.log(formatter.format(5));
// Output: "5"
console.log(formatter.format(5.5));
// Output: "5.5"
console.log(formatter.format(5.555));
// Output: "5.56"
Такой подход убирает завершающие нули, но всё равно ограничивает точность двумя знаками после запятой. Это удобно для отображения измерений или статистики, где лишние нули не несут информации.
Значение по умолчанию для minimumFractionDigits — 0 при обычном форматировании чисел, так что этот параметр можно не указывать.
const formatter = new Intl.NumberFormat("en-US", {
maximumFractionDigits: 2
});
console.log(formatter.format(5));
// Output: "5"
console.log(formatter.format(5.5));
// Output: "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));
});
// Output:
// "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));
// Output varies by user's locale
// For en-US: "19.99"
// For de-DE: "19,99"
// For fr-FR: "19,99"
Также можно передать весь массив navigator.languages, чтобы API Intl выбрал первый поддерживаемый язык из предпочтений пользователя.
const formatter = new Intl.NumberFormat(navigator.languages, {
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
Такой подход обеспечивает автоматический выбор следующего варианта, если первый язык пользователя не поддерживается.