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

Форматирование процентов в JavaScript реализуется через Intl.NumberFormat с опцией style: 'percent'. Этот режим предназначен для отображения дробных значений в виде процентов с автоматическим масштабированием и локализованным оформлением.

Базовый принцип работы процентного формата

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

const formatter = new Intl.NumberFormat('ru-RU', {
  style: 'percent'
});

formatter.format(0.25); // "25%"
formatter.format(0.5);  // "50%"
formatter.format(1);    // "100%"

Ключевая особенность заключается в том, что входное значение трактуется как доля единицы:

  • 0.011%
  • 0.110%
  • 1100%
  • 2200%

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


Локализация процентов

Форматирование процентов зависит от локали, включая символ процента, пробелы и порядок элементов.

const ru = new Intl.NumberFormat('ru-RU', { style: 'percent' });
const en = new Intl.NumberFormat('en-US', { style: 'percent' });

ru.format(0.75); // "75 %"
en.format(0.75); // "75%"

Различия между локалями могут включать:

  • наличие неразрывного пробела перед %
  • позицию символа процента
  • тип используемых цифр (арабские, индийские и др.)

Управление точностью

Процентный формат поддерживает стандартные параметры округления и точности:

const formatter = new Intl.NumberFormat('ru-RU', {
  style: 'percent',
  minimumFractionDigits: 2,
  maximumFractionDigits: 2
});

formatter.format(0.1234); // "12,34 %"

Основные параметры:

  • minimumFractionDigits — минимальное количество знаков после запятой
  • maximumFractionDigits — максимальное количество знаков после запятой
  • minimumSignificantDigits / maximumSignificantDigits — управление значащими цифрами

Пример с значащими цифрами:

const formatter = new Intl.NumberFormat('ru-RU', {
  style: 'percent',
  minimumSignificantDigits: 3,
  maximumSignificantDigits: 3
});

formatter.format(0.12345); // "12,3 %"

Поведение округления

Округление влияет на конечный вид процента после масштабирования. Например, значение 0.155 при стандартной точности:

const formatter = new Intl.NumberFormat('ru-RU', {
  style: 'percent',
  maximumFractionDigits: 0
});

formatter.format(0.155); // "16 %"

Сначала происходит умножение на 100 → 15.5, затем округление до 16.


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

Отрицательные значения отображаются с соответствующим знаком:

const formatter = new Intl.NumberFormat('ru-RU', {
  style: 'percent'
});

formatter.format(-0.2); // "-20 %"

Для некоторых локалей возможны различия в позиции знака минус, но семантика сохраняется: отрицательная доля от 1.


Отображение знака

Параметр signDisplay управляет отображением знака:

const formatter = new Intl.NumberFormat('ru-RU', {
  style: 'percent',
  signDisplay: 'always'
});

formatter.format(0.1);  // "+10 %"
formatter.format(-0.1); // "-10 %"

Варианты:

  • auto — знак только для отрицательных (по умолчанию)
  • always — знак всегда
  • never — без знаков
  • exceptZero — знак для всех, кроме нуля

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

Некоторые локали поддерживают альтернативные системы цифр:

const formatter = new Intl.NumberFormat('ar-EG', {
  style: 'percent'
});

formatter.format(0.5);

Результат может включать арабско-индийские цифры и локализованный символ процента.


Форматирование частей строки

Метод formatToParts позволяет получить структурированное представление результата:

const formatter = new Intl.NumberFormat('ru-RU', {
  style: 'percent'
});

formatter.formatToParts(0.25);

Результат:

[
  { type: 'integer', value: '25' },
  { type: 'literal', value: ' ' },
  { type: 'percentSign', value: '%' }
]

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


Особенности масштабирования

Процентный формат всегда применяет фиксированное масштабирование ×100. Это влияет на все вычисления:

Входное значение Отображение
0.003 0.3%
0.03 3%
0.3 30%
3 300%

Это поведение нельзя отключить средствами Intl.NumberFormat.


Комбинация с другими параметрами форматирования

Процентный стиль может комбинироваться с настройками группировки и округления:

const formatter = new Intl.NumberFormat('ru-RU', {
  style: 'percent',
  useGrouping: true,
  maximumFractionDigits: 1
});

formatter.format(0.1234); // "12,3 %"

Также поддерживается изменение компактного представления:

const formatter = new Intl.NumberFormat('en-US', {
  style: 'percent',
  notation: 'compact'
});

formatter.format(0.25);

Граничные случаи

Очень малые значения

new Intl.NumberFormat('en-US', {
  style: 'percent',
  maximumFractionDigits: 2
}).format(0.00004);

Результат может быть округлён до "0%", что зависит от настроек точности.

Очень большие значения

formatter.format(12); // "1200%"

Процентный формат не ограничивает диапазон значений.


Поведение с NaN и Infinity

const formatter = new Intl.NumberFormat('ru-RU', {
  style: 'percent'
});

formatter.format(NaN);      // "NaN %"
formatter.format(Infinity); // "∞ %"

Поведение соответствует общим правилам Intl.NumberFormat.


Практические особенности использования

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

Типичная ошибка:

formatter.format(50); // "5000 %" ❌

Корректное использование:

formatter.format(0.5); // "50 %" ✅

Взаимодействие с финансовыми и аналитическими данными

В прикладных сценариях процентный формат часто применяется для:

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

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