Системы счисления

В JavaScript интернационализация чисел строится вокруг механизмов, которые позволяют отображать одни и те же числовые значения в различных системах записи цифр. Ключевая роль здесь принадлежит объекту Intl.NumberFormat, поддерживающему параметр numberingSystem, а также расширениям локали вида -u-nu.


В разных языках и культурах используются различные способы записи чисел. Даже при одинаковой математической сущности числа его визуальное представление может радикально отличаться:

  • арабские цифры (0–9), привычные в европейских системах;
  • арабо-индийские цифры;
  • деванагари;
  • китайские числовые формы;
  • тайские цифры и другие региональные системы.

В контексте Intl под системой счисления понимается не математическая база, а графическая система представления цифр.


Базовая система: latn

По умолчанию большинство локалей используют систему:

latn

Она соответствует привычным арабским цифрам:

new Intl.NumberFormat('en-US').format(123456);
// "123,456"

Даже если явно не указано, большинство европейских и американских локалей используют именно latn.


Параметр numberingSystem в Intl.NumberFormat

Intl.NumberFormat позволяет явно задавать систему цифр через опцию numberingSystem.

new Intl.NumberFormat('ar-EG', {
  numberingSystem: 'latn'
}).format(123456);

Результат:

123,456

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


Арабская система цифр: arab

Одна из наиболее известных альтернативных систем:

new Intl.NumberFormat('ar-EG', {
  numberingSystem: 'arab'
}).format(123456);

Результат:

١٢٣٬٤٥٦

Особенность заключается в том, что:

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

Расширенная арабская система: arabext

Система arabext используется в некоторых вариантах арабских локалей и отличается более формализованными символами:

new Intl.NumberFormat('ar-EG', {
  numberingSystem: 'arabext'
}).format(987654);

Результат:

٩٨٧٬٦٥٤

Различие между arab и arabext в деталях типографики и исторически закреплённых стандартах отображения.


Деванагари: deva

Используется в индийских языках, включая хинди:

new Intl.NumberFormat('hi-IN', {
  numberingSystem: 'deva'
}).format(123456);

Результат:

१२३,४५६

Особенность системы:

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

Бенгальская система: beng

new Intl.NumberFormat('bn-BD', {
  numberingSystem: 'beng'
}).format(123456);

Результат:

১২৩,৪৫৬

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


Китайская система: hanidec

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

new Intl.NumberFormat('zh-CN', {
  numberingSystem: 'hanidec'
}).format(123456);

Результат:

一二三四五六

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

  • отсутствуют десятичные запятые в классическом виде;
  • цифры представляются иероглифами от 0 до 9;
  • используется преимущественно в контекстах счётчиков и нумерации.

Тайская система: thai

new Intl.NumberFormat('th-TH', {
  numberingSystem: 'thai'
}).format(123456);

Результат:

๑๒๓,๔๕๖

Эта система широко используется в Таиланде наряду с латинской.


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

Система счисления может быть задана не только через параметр numberingSystem, но и через расширение Unicode в строке локали:

new Intl.NumberFormat('ar-EG-u-nu-arab').format(123456);

Здесь:

  • u — расширение Unicode;
  • nu — ключ numbering system;
  • arab — конкретная система цифр.

Аналогично:

new Intl.NumberFormat('hi-IN-u-nu-deva').format(123456);

Приоритеты выбора системы

При форматировании чисел действует следующая логика:

  1. Явно указан numberingSystem в опциях — имеет наивысший приоритет.
  2. Если не указан, но есть -u-nu-... в локали — используется он.
  3. Если ничего не задано — используется стандарт локали.
  4. Если система не поддерживается — происходит fallback к latn.

Список поддерживаемых систем

Чаще всего в движках JavaScript встречаются:

  • latn — латинская
  • arab — арабская
  • arabext — расширенная арабская
  • thai — тайская
  • deva — деванагари
  • beng — бенгальская
  • guru — гурмукхи
  • hanidec — китайская десятичная
  • khmr — кхмерская
  • mymr — бирманская
  • tibt — тибетская

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


Влияние системы счисления на форматирование

Система цифр влияет только на визуальное представление чисел, но не на:

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

Пример:

new Intl.NumberFormat('en-US', {
  numberingSystem: 'thai'
}).format(1000000);

Результат:

๑,๐๐๐,๐๐๐

Числовая структура остаётся прежней, меняются только символы.


Взаимодействие с другими параметрами NumberFormat

Системы счисления работают совместно с другими настройками:

style

new Intl.NumberFormat('hi-IN', {
  numberingSystem: 'deva',
  style: 'currency',
  currency: 'INR'
}).format(1234.56);

minimumFractionDigits и maximumFractionDigits

new Intl.NumberFormat('ar-EG', {
  numberingSystem: 'arab',
  minimumFractionDigits: 2
}).format(12.5);

Ограничения и особенности реализации

  • Intl не выполняет конвертацию систем счисления в математическом смысле.
  • Нет поддержки пользовательских наборов цифр.
  • Нельзя изменить порядок цифр или правила позиционирования.
  • Поддержка зависит от ICU-данных в окружении (Node.js или браузер).

Практическая значимость систем счисления

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

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

Влияние Unicode-расширений на локализацию чисел

Unicode-расширения позволяют объединять локаль и систему счисления в одном идентификаторе:

'hi-IN-u-nu-deva'
'ar-SA-u-nu-arab'
'th-TH-u-nu-thai'

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