Научная нотация

Intl.NumberFormat — это часть ECMAScript Internationalization API, предназначенная для локализованного форматирования чисел. Одной из его наиболее мощных возможностей является поддержка научной и инженерной записи чисел через параметр notation.

Научная нотация используется для компактного представления очень больших и очень малых чисел в виде произведения коэффициента и степени десяти:

общая форма:

  • ( a ^n ), где ( 1 |a| < 10 )

В JavaScript это поведение активируется через Intl.NumberFormat:

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

formatter.format(123456789); 
// "1.235E8"

Ключевой особенностью является автоматическая нормализация числа и его представление в экспоненциальной форме с учётом локали и настроек точности.


Параметр notation и режимы представления

Параметр notation определяет стратегию отображения числа:

  • standard — обычное форматирование
  • scientific — научная нотация (экспоненциальная форма)
  • engineering — инженерная нотация (степень кратна 3)
  • compact — сокращённая запись (например, 1K, 1M)

Научная нотация отличается от инженерной тем, что степень десяти не ограничивается кратностью трём.

const nfScientific = new Intl.NumberFormat('en-US', {
  notation: 'scientific'
});

const nfEngineering = new Intl.NumberFormat('en-US', {
  notation: 'engineering'
});

nfScientific.format(987654321);
// "9.877E8"

nfEngineering.format(987654321);
// "987.654E6"

Поведение коэффициента и округление

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

const formatter = new Intl.NumberFormat('en-US', {
  notation: 'scientific',
  maximumFractionDigits: 2
});

formatter.format(123456789);
// "1.23E8"

Если не заданы ограничения, движок использует стандартные правила округления для локали.


Влияние локали на формат экспоненты

Локаль влияет не только на десятичный разделитель, но и на представление экспоненты.

const us = new Intl.NumberFormat('en-US', {
  notation: 'scientific'
});

const de = new Intl.NumberFormat('de-DE', {
  notation: 'scientific'
});

us.format(1234567);
// "1.235E6"

de.format(1234567);
// "1,235E6"

В немецкой локали используется запятая как десятичный разделитель, но обозначение экспоненты остаётся стандартным E.


Инженерная и научная нотация: различия в глубине представления

Инженерная нотация стремится группировать порядок числа по степеням 10³, что удобно в технических и физических расчётах.

const engineering = new Intl.NumberFormat('en-US', {
  notation: 'engineering'
});

engineering.format(1234567890);
// "1.235E9"

engineering.format(123456789);
// "123.457E6"

В отличие от научной записи, инженерная обеспечивает более “человекоориентированное” масштабирование, особенно в контексте единиц измерения (кило-, мега-, гига-).


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

Научная нотация корректно обрабатывает отрицательные значения и ноль:

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

formatter.format(-987654);
// "-9.877E5"

formatter.format(0);
// "0E0"

Для нуля экспонента фиксируется как 0, что сохраняет математическую согласованность представления.


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

Intl.NumberFormat позволяет комбинировать научную нотацию с дополнительными настройками:

  • signDisplay
  • minimumSignificantDigits
  • maximumSignificantDigits
  • useGrouping
const formatter = new Intl.NumberFormat('en-US', {
  notation: 'scientific',
  signDisplay: 'always',
  maximumSignificantDigits: 4
});

formatter.format(0.0123456);
// "+1.235E-2"

Параметр signDisplay: 'always' принудительно отображает знак, включая положительные числа.


Значащие цифры и контроль точности

При работе с научной нотацией часто используется управление значащими цифрами:

const formatter = new Intl.NumberFormat('en-US', {
  notation: 'scientific',
  minimumSignificantDigits: 3,
  maximumSignificantDigits: 5
});

formatter.format(123456789);
// "1.2346E8"

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


Поведение при очень малых значениях

Для чисел меньше единицы экспонента становится отрицательной:

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

formatter.format(0.0000123);
// "1.23E-5"

Число автоматически нормализуется так, чтобы коэффициент оставался в диапазоне от 1 до 10.


Особенности реализации в движках JavaScript

Поведение Intl.NumberFormat зависит от ICU-библиотеки, используемой в движке:

  • V8 (Chrome, Node.js)
  • SpiderMonkey (Firefox)
  • JavaScriptCore (Safari)

Различия могут проявляться в:

  • округлении пограничных значений
  • форматировании экспоненты
  • поддержке новых параметров notation в старых версиях окружений

Производительность форматирования

Форматирование через Intl.NumberFormat включает тяжёлую локализационную логику, поэтому создание экземпляра форматтера имеет смысл выполнять один раз:

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

function format(numbers) {
  return numbers.map(n => formatter.format(n));
}

Повторное создание форматтера для каждого числа приводит к избыточным затратам на инициализацию ICU-таблиц.


Типовые сценарии применения научной нотации

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

Ограничения и поведение в крайних случаях

При работе с экстремальными значениями (очень большие или очень малые числа) возможны следующие эффекты:

  • потеря точности IEEE-754 для Number
  • переход к экспоненциальной форме даже без notation
  • ограничение диапазона значащих цифр
Number.MAX_VALUE;
// 1.7976931348623157e+308

new Intl.NumberFormat('en-US', {
  notation: 'scientific'
}).format(Number.MAX_VALUE);
// "1.798E308"

Сочетание с BigInt

Intl.NumberFormat поддерживает BigInt, что особенно важно для научной нотации больших целых чисел:

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

formatter.format(1234567890123456789012345n);
// "1.234568E24"

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