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

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

1.23E6
4.56E-3
9.81E8

Библиотека Globalize использует данные CLDR и API Intl, обеспечивая локализованное форматирование чисел, включая поддержку научной нотации с учётом региональных правил записи.

Подключение Globalize

Минимальный набор зависимостей:

<script src="cldr.js"></script>
<script src="cldr/event.js"></script>
<script src="cldr/supplemental.js"></script>
<script src="globalize.js"></script>
<script src="globalize/number.js"></script>

Подключение CLDR-данных:

Globalize.load(
  cldrDataEntires
);

Globalize.locale("en");

Форматирование числа в научной нотации

Метод numberFormatter() поддерживает шаблоны ICU.

Простейший пример:

const formatter = Globalize.numberFormatter({
  raw: "0.###E0"
});

console.log(formatter(123456));
// 1.235E5

Разбор шаблона

Шаблон:

0.###E0

означает:

Элемент Назначение
0 обязательная цифра
# необязательная цифра
E разделитель экспоненты
0 после E обязательная степень

Форматирование больших чисел

const formatter = Globalize.numberFormatter({
  raw: "0.00E0"
});

console.log(formatter(987654321));

Результат:

9.88E8

Что произошло

Число:

987654321

преобразуется в:

9.87654321 × 10^8

После округления:

9.88E8

Форматирование малых чисел

const formatter = Globalize.numberFormatter({
  raw: "0.###E0"
});

console.log(formatter(0.00000042));

Результат:

4.2E-7

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

Количество символов 0 и # влияет на точность вывода.

Фиксированное количество знаков

const formatter = Globalize.numberFormatter({
  raw: "0.000E0"
});

console.log(formatter(12345));

Результат:

1.235E4

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

const formatter = Globalize.numberFormatter({
  raw: "0.##E0"
});

console.log(formatter(12345));

Результат:

1.23E4

Разница между 0 и #

Символ 0

Гарантирует наличие цифры:

const formatter = Globalize.numberFormatter({
  raw: "0.000E0"
});

console.log(formatter(1200));

Результат:

1.200E3

Символ #

Отображает цифру только при необходимости:

const formatter = Globalize.numberFormatter({
  raw: "0.###E0"
});

console.log(formatter(1200));

Результат:

1.2E3

Локализация научной нотации

Globalize учитывает локальные правила отображения чисел.

Английская локаль

Globalize.locale("en");

const formatter = Globalize.numberFormatter({
  raw: "0.###E0"
});

console.log(formatter(12345.67));

Результат:

1.235E4

Немецкая локаль

Globalize.locale("de");

const formatter = Globalize.numberFormatter({
  raw: "0.###E0"
});

console.log(formatter(12345.67));

Результат:

1,235E4

Основное отличие — использование запятой в качестве десятичного разделителя.

Использование положительных и отрицательных шаблонов

Globalize поддерживает раздельное форматирование положительных и отрицательных чисел.

const formatter = Globalize.numberFormatter({
  raw: "0.##E0;(-0.##E0)"
});

console.log(formatter(15000));
console.log(formatter(-15000));

Результат:

1.5E4
(-1.5E4)

Принудительное отображение знака степени

const formatter = Globalize.numberFormatter({
  raw: "+0.##E+0"
});

console.log(formatter(12000));

Результат:

+1.2E+4

Работа с нулём

const formatter = Globalize.numberFormatter({
  raw: "0.###E0"
});

console.log(formatter(0));

Результат:

0E0

Округление чисел

Globalize автоматически округляет число согласно шаблону.

const formatter = Globalize.numberFormatter({
  raw: "0.00E0"
});

console.log(formatter(99999));

Результат:

1.00E5

Причина изменения степени

Исходное значение:

9.9999E4

После округления:

10.00E4

Нормализованный формат:

1.00E5

Экспоненциальная запись для инженерных расчётов

Научная нотация часто используется:

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

Пример:

const formatter = Globalize.numberFormatter({
  raw: "0.0000E0"
});

const mass = 0.000000000000000000000000000910938;

console.log(formatter(mass));

Результат:

9.1094E-31

Использование с пользовательскими функциями

Форматтер рекомендуется создавать один раз и переиспользовать.

Неэффективный вариант

function formatNumber(value) {
  return Globalize.numberFormatter({
    raw: "0.###E0"
  })(value);
}

При каждом вызове создаётся новый formatter.

Оптимизированный вариант

const scientificFormatter = Globalize.numberFormatter({
  raw: "0.###E0"
});

function formatNumber(value) {
  return scientificFormatter(value);
}

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

const formatter = Globalize.numberFormatter({
  raw: "0.##E0"
});

const values = [
  1200,
  4500000,
  0.00034
];

const result = values.map(formatter);

console.log(result);

Результат:

[
  "1.2E3",
  "4.5E6",
  "3.4E-4"
]

Использование в таблицах

const formatter = Globalize.numberFormatter({
  raw: "0.###E0"
});

const data = [
  { name: "Distance", value: 149600000000 },
  { name: "Atom radius", value: 0.000000000053 }
];

data.forEach(item => {
  console.log(item.name, formatter(item.value));
});

Результат:

Distance 1.496E11
Atom radius 5.3E-11

Комбинирование с единицами измерения

const formatter = Globalize.numberFormatter({
  raw: "0.##E0"
});

const speed = 299792458;

console.log(`${formatter(speed)} m/s`);

Результат:

3E8 m/s

Ограничения научной нотации

Сложность восприятия

Для неподготовленного пользователя запись:

4.2E7

может быть менее понятной, чем:

42 000 000

Потеря визуальной наглядности

Научная нотация скрывает количество разрядов.

Возможные ошибки округления

При недостаточной точности:

const formatter = Globalize.numberFormatter({
  raw: "0.0E0"
});

console.log(formatter(199999));

Результат:

2.0E5

Часть значимых цифр теряется.

Отличие научной и инженерной нотации

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

Мантисса находится в диапазоне:

1 ≤ x < 10

Пример:

1.2E5

Инженерная нотация

Степень всегда кратна трём:

120E3

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

Реализация инженерной нотации

function engineeringNotation(value) {
  if (value === 0) {
    return "0E0";
  }

  const exponent = Math.floor(Math.log10(Math.abs(value)) / 3) * 3;
  const mantissa = value / Math.pow(10, exponent);

  return `${mantissa.toFixed(2)}E${exponent}`;
}

console.log(engineeringNotation(1234567));

Результат:

1.23E6

Использование совместно с Intl

Globalize часто применяется как надстройка над возможностями Intl.

Пример сравнения:

Intl

const value = 123456;

console.log(
  new Intl.NumberFormat("en", {
    notation: "scientific"
  }).format(value)
);

Globalize

Globalize.locale("en");

const formatter = Globalize.numberFormatter({
  raw: "0.###E0"
});

console.log(formatter(value));

Преимущества Globalize

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

Проверка корректности шаблона

Некорректный шаблон вызывает ошибку:

const formatter = Globalize.numberFormatter({
  raw: "E0"
});

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

Invalid pattern

Практический пример: форматирование физических констант

Globalize.locale("en");

const formatter = Globalize.numberFormatter({
  raw: "0.#####E0"
});

const constants = {
  speedOfLight: 299792458,
  electronMass: 9.10938356e-31,
  planck: 6.62607015e-34
};

Object.entries(constants).forEach(([name, value]) => {
  console.log(name, formatter(value));
});

Результат:

speedOfLight 2.99792E8
electronMass 9.10938E-31
planck 6.62607E-34

Практический пример: компактное отображение статистики

const formatter = Globalize.numberFormatter({
  raw: "0.##E0"
});

const metrics = [
  120000000,
  9876543210,
  0.0000012
];

metrics.forEach(value => {
  console.log(formatter(value));
});

Результат:

1.2E8
9.88E9
1.2E-6