Number и BigInt: Насколько точны числовые типы данных в JavaScript

Number и BigInt: Насколько точны числовые типы данных в JavaScript
Антон Ларичев
Основатель школы PurpleSchool

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

Number и BigInt

С момента своего создания в 1995 году, в JavaScript был только один числовой тип данных - Number, который имеет ограничения в пределах 64-битового формата IEEE-754. Это означает, что безопасно доступны целые числа в диапазоне от-(2^53 - 1) до (2^53 - 1) из-за ограничений на хранение позиции точки. Поэтому числа, выходящие за эти границы, будут преобразованы в Infinity или -Infinity. Однако с выходом ES2020 появился новый тип данных - BigInt, который позволяет работать с целыми числами любой длинны. Для создания значения с таким типом достаточно добавить n в конце числа при вводе вручную или передать нужное значение в функцию BigInt.

Number и BigInt: Насколько точны числовые типы данных в JavaScript

BigInt во многих ситуациях ведет себя как Number, например с большинством математических операторов, а так же при преобразовании в Boolean, использовании логических операторов ||, && , ! и при проверке условий. Но не может его полностью заменить т.к. имеет ряд ограничений:

  • Оператор деления округляет результат в меньшую сторону до целого потому что BigInt представляет только целые числа.
  • BigInt нельзя смешивать в одних выражениях с Number, для подобных операций следует приводить значения к одному типу данных, но не стоит забывать, что при приведении Number к BigInt потеряется вся дробная часть, а при приведении BigInt к Number - точность и обход ограничения максимального значения.
  • Унарный плюс не подойдет для приведения BigInt к Number поэтому следует использовать глобальный объект Number.
  • Строгое сравнение “одинаковых” значений этих двух типов данных вернет false (1n === 1 //false), при этом другие операторы сравнения будут работать как обычно вне зависимости от того, какими типами данных представлены числа, как и метод .sort массивов, элементы которых являются любым из числовых типов.
  • Для использования объекта Math BigInt так же придется приводить к Number.
  • Если вы попытаетесь использовать функцию JSON.stringify() на значении типа BigInt, то столкнетесь с ошибкой TypeError. Это происходит потому что по умолчанию значения BigInt не могут быть правильно преобразованы в формат JSON.
Number и BigInt: Насколько точны числовые типы данных в JavaScript

Неточности при вычислениях в JavaScript

BigInt призван не только снять ограничение по размеру положительных и отрицательных числе в JavaScript, но и решить проблему неточности при работе с большими числами. Как мы уже знаем, JavaScript хранит Number в 64-битном формате IEEE-754. Из этих 64 бит один хранит знак числа, 11 - позицию десятичной дроби и оставшиеся 52 - само число и если число занимает больше 52 бит - часть информации будет утрачена. BigInt предотвращает такую потерю.

Number и BigInt: Насколько точны числовые типы данных в JavaScript

Однако BigInt подходит только для целых чисел. При работе дробями так же могут возникать неточности вычислений из-за переполнения памяти, отведенной под знаки после запятой. На самом деле такие неточности возникают чаще, чем кажется, но формат IEEE-754 незаметно для нас округляет дробь до ближайшего возможного числа. Видим же мы последствия переполнения 11 бит, в основном при математических операциях с дробями. Тут уже нам самим нужно при написании кода позаботиться о корректности вывода результатов операций с дробями, например округлив этот результат до допустимого знака после запятой с помощью метода .toFixed() .

Number и BigInt: Насколько точны числовые типы данных в JavaScript

Способы записи чисел в JavaScript

В JavaScript существует несколько способов записать число с большим количеством знаков так, что бы его было удобно прочесть. Так знак нижнего подчеркивания ( _ ) внутри записи числа не повлияет на его значение, но упростит прочтение, а для очень больших или очень маленьких чисел, с большим количеством знаков знаков после запятой, можно добавить букву “e” и указать после нее количество нулей (положительное для записи целого числа и отрицательное для дроби). Так миллиард можно записать как 1e9, а одну миллиардную долю как 1e-9. Важно помнить что запись через “e” не доступна в BigInt и не защищает от неточности вычислений.

Number и BigInt: Насколько точны числовые типы данных в JavaScript

Довольно часто встречаются записи значений в виде строки с единицей измерения, например 100px или 20$. Что бы извлечь из такой записи числовое значение можно воспользоваться функциями parseInt() для целых чисел или parseFloat() для дробей. Однако стоит помнить, что обе эти функции “ищут” числовые значения с начала строки и вернут NaN при парсинге строки типа “у Саши было 2 яблока”, проигнорировав цифру 2. Для поиска по подобным строкам лучше использовать регулярные выражения.

Number и BigInt: Насколько точны числовые типы данных в JavaScript

Заключение

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

JavaScript с нуля - основы языка и практика для начинающих

- 16 часов коротких лекций по 10 - 15 минут

- 15 упражнений для закрепления на практике1

- 5 тестов для проверки знаний

- Рейтинг ⭐ 4.9 на основании отзывов

- 30-ти дневная гарантия возврата денег

JavaScript Advanced - продвинутые концепции языка и ООП

- 18 часов коротких лекций по 10 - 15 минут

- 30упражнений для закрепления на практике

- 14 тестов для проверки знаний

- Рейтинг ⭐ 4.9 на основании отзывов

- 30-ти дневная гарантия возврата денег

Начать дискуссию