64-битный тип Number в JavaScript вполне подходит для большинства целей, но если вам нужны очень большие числа или больше десятичных разрядов, чем он может представить, вам может прийти на помощь тип BigNumber из библиотеки math.js. В этой статье я покажу тип BigNumber в действии.

Этот проект состоит из файла HTML, файла JavaScript и файла CSS, которые находятся в репозитории itHub. Я также включил минимизированную версию библиотеки math.js, math.min.js.

Ограничения числового типа JavaScript

Тип JavaScript Number подходит для большинства целей как с точки зрения наибольшего и наименьшего числа, так и с максимальным количеством знаков после запятой. Однако он ограничен тем, сколько вы можете втиснуть в 64 бита, поэтому, прежде чем перейти к основной теме этой статьи, math.js BigNumber, я кратко расскажу, каковы ограничения типа JavaScript Number.

JavaScript предоставляет нам пару констант, Number.MAX_SAFE_INTEGER и Number.MIN_SAFE_INTEGER, а также метод под названием Number.isSafeInteger, который позволяет нам проверить, не думаем ли мы, что можем наткнуться на опасную территорию с очень большими числами.

Первая часть кода JavaScript, прилагаемая к этой статье, показывает использование этих констант и методов.

В onload есть три вызова функций, второй и третий пока закомментированы. После onload идет короткая функция, которая записывает текст прямо на веб-страницу.

В safeIntegers мы просто выводим Number.MAX_SAFE_INTEGER и Number.MIN_SAFE_INTEGER перед созданием нескольких констант для проверки безопасности. Затем выводится каждый из них, за которым следует результат вызова Number.isSafeInteger с ним. Если вы откроете mathjsbignumber.htm в своем браузере, вы увидите это.

Тип JavaScript BigInt

В JavaScript есть собственное частичное решение проблемы ограничений Number, тип BigInt. Как следует из названия, это целочисленный тип, а не вещественный или с плавающей запятой, и он несовместим с методами Math. Поэтому его полезность ограничена, но в следующем методе я кратко покажу его использование.

Во-первых, мы создаем пару BigInts — здесь это делается путем добавления к числу суффикса n, но вы также можете вызвать конструктор BigInt, например:

const bigNo = BigInt(9007199254740992);

Вызов typeof для BigInt возвращает bigint, а затем печатаются две константы. Затем мы делим 3n на 2n просто для того, чтобы продемонстрировать, что это целочисленный тип; результатом будет 1 с потерей десятичной части. Наконец, просто как напоминание о том, что методы Math не работают на BigInts, я попробовал его с Math.min и Math.sign. Оба они будут вызывать ошибки, поэтому эти фрагменты кода находятся в блоках try/catch.

Если вы прокрутите вверх до функции onload, закомментируете safeIntegers();, раскомментируете BigInts(); и обновите веб-страницу, вы увидите этот вывод.

Интересно видеть сообщения об ошибках: методы Math пытаются преобразовать аргументы в типы Number, но терпят неудачу. Это так же хорошо, как если бы они потеряли точность.

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

Основная особенность: тип math.js BigNumber

Тип BigNumber библиотеки math.js может представлять действительные числа или числа с плавающей запятой и может использоваться с методами библиотеки. В финальной функции я покажу ее в использовании.

Во-первых, я создал BigNumber с размером наблюдаемой вселенной в километрах и вывел значение с фиксированной нотацией; это отформатирует вывод полностью, а не 8.8e+26. (Очевидно, что световые годы были бы более разумной единицей, но это только для демонстрационных целей.)

Затем мы выполняем несколько операций над BigNumbers с помощью методов math.js, чего нельзя сделать с помощью методов JavaScript BigInts и Math, как мы только что видели.

Следующие несколько строк кода демонстрируют, как изменить точность BigNumbers, в данном случае с квадратным корнем из 2, которое является иррациональным числом. По умолчанию используется 64 значащих цифры, но здесь я также использую 32 и 128. Использование BigNumbers значительно медленнее, чем тип Number, тем медленнее, чем больше цифр, поэтому важно использовать только ту точность, которая вам нужна. Обратите внимание, что даже при значении 32 у нас все еще примерно в два раза больше точных знаков после запятой, чем у типа Number.

Наконец, я создал пару констант для очень маленьких и очень больших чисел. Первая — это планковская длина (в метрах), которую я не буду здесь описывать, но вы можете прочитать статью в Википедии. Достаточно сказать, что это очень-очень мало!

Второе число — это количество атомов во Вселенной. Обозначение 1e+80 означает 10^80 и является приблизительным. Очевидно!

Закомментируйте BigInts(); в onload, раскомментируйте BigNumbers(); и перезагрузите страницу. Это результат, несколько обрезанный. Очень длинные числа идут намного дальше вправо.

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

  • Создайте BigNumber с math.bignumber(880000000000000000000000000) или math.bignumber(1e+80)
  • Установите минимальное количество значащих цифр, необходимое для оптимальной эффективности.
  • Используйте любой из методов библиотеки math.js с BigNumbers: они распознают, когда вы передаете BigNumber аргументов, и вернут BigNumber
  • Используйте math.format . . . {notation: ‘fixed’}, если вы хотите видеть все цифры, а не что-то вроде 8.8e+26

Эта статья ранее публиковалась на моем сайте CodeDrome