Skip to main content

BigInt проти Number

BigInt це спеціальний числовий тип JavaScript, який дозволяє працювати з цілими числами довільної довжини, без обмеження 2^53 - 1. Значення створюється додаванням n у кінці числа або викликом функції BigInt().

javascript
const big = 123456789012345678901234567890n; const big2 = BigInt("123456789012345678901234567890");

Теорія

TL;DR

  • Усі звичайні числа в JavaScript мають тип Number і зберігаються у форматі IEEE 754 (64-бітне число з рухомою крапкою).
  • Точно представляти цілі можна лише до Number.MAX_SAFE_INTEGER === 9007199254740991 (2^53 - 1), далі починається втрата точності.
  • BigInt знімає це обмеження: довжина цілого числа обмежена лише пам'яттю.
  • Створюється літералом із суфіксом n (10n) або функцією BigInt(10), BigInt("9007199254740995").
  • Дробів не підтримує: BigInt(1.5) кидає TypeError, а ділення 5n / 2n відкидає дробову частину.
  • Не змішується з Number в арифметиці, не працює з Math і не серіалізується через JSON.stringify().

Швидкий приклад

javascript
const a = 10n; // літерал const b = BigInt(10); // через функцію const c = BigInt("9007199254740995"); // з рядка console.log(a + b); // 20n console.log(c + 1n); // 9007199254740996n

Проблема звичайних чисел

У JavaScript усі звичайні числа мають тип Number і зберігаються у форматі IEEE 754 (64-бітне число з рухомою крапкою). Це означає, що мова може точно представляти цілі числа лише до:

javascript
Number.MAX_SAFE_INTEGER === 9007199254740991; // 2^53 - 1

Якщо число більше, починається втрата точності:

javascript
const num = 9007199254740991; console.log(num + 1); // 9007199254740992, коректно console.log(num + 2); // 9007199254740992, помилка

Числа «злиплися»: рушій уже не може відрізнити +1 від +2, бо сусідні цілі в цьому діапазоні не мають окремого представлення.

BigInt вирішує саме цю проблему:

javascript
const big = 9007199254740991n; console.log(big + 1n); // 9007199254740992n console.log(big + 2n); // 9007199254740993n, точно

Як створити BigInt

Є три способи, і жоден з них не приймає дробів:

javascript
const a = 10n; // літерал const b = BigInt(10); // через функцію const c = BigInt("9007199254740995"); // з рядка
javascript
BigInt(1.5); // TypeError: Cannot convert 1.5 to a BigInt

Арифметика з BigInt

Підтримуються базові операції, але всі вони цілочисельні:

javascript
const x = 5n; const y = 2n; console.log(x + y); // 7n console.log(x - y); // 3n console.log(x * y); // 10n console.log(x / y); // 2n, дробова частина відкидається console.log(x ** y); // 25n

Ділення завжди повертає ціле число, залишок просто відкидається (5n / 2n це 2n, а не 2.5).

Number і BigInt не можна змішувати в одному арифметичному виразі:

javascript
const big = 10n; const num = 5; console.log(big + num); // TypeError: Cannot mix BigInt and other types

Потрібне явне приведення типу:

javascript
console.log(big + BigInt(num)); // 15n // або console.log(Number(big) + num); // 15

Порівняння, на відміну від арифметики, працює: при нестрогому порівнянні тип приводиться автоматично.

javascript
10n == 10; // true, нестроге порівняння 10n === 10; // false, строге порівняння, типи різні 10n < 20; // true

Функції Math з BigInt несумісні:

javascript
Math.sqrt(4n); // TypeError: Cannot convert a BigInt value to a number

За потреби значення спочатку приводять: Math.sqrt(Number(4n)), пам'ятаючи, що на дуже великих числах таке приведення знову втратить точність.

Number проти BigInt

ОсобливістьNumberBigInt
Типчисло з рухомою крапкоюціле число довільної довжини
Максимальна точністьдо 2^53 - 1необмежена
Підтримка дробівтакні
Операціїстандартністандартні, але тільки цілочисельні
Сумісністьскрізьз 2020 року
Використання з JSONтакні, JSON.stringify() кидає помилку
Приведення типівсумісний з усімтреба приводити явно
Коли братизвичайні числа і дробидуже великі цілі

Де застосовують BigInt

Зберігання великих ідентифікаторів, наприклад з бази даних, де 64-бітний id не вміщується в безпечний діапазон Number:

javascript
const userId = 183748917238479182374981273n;

Криптографія, блокчейн і фінанси, де округлення неприпустиме:

javascript
const balance = 999999999999999999999999999n; const transfer = 250000000000000000000n; console.log(balance - transfer); // рахує точно

Сюди ж належать лічильники з дуже великими значеннями, часові мітки в наносекундах і будь-яка робота з цілими числами, де помилка на одиницю неприпустима.

Типові помилки

  • Змішування типів в арифметиці. 10n + 5 це TypeError, а не 15n. Приводьте явно: 10n + BigInt(5) або Number(10n) + 5.
  • Очікування дробового ділення. 7n / 2n дає 3n, залишок відкидається мовчки, без жодної помилки.
  • Спроба створити BigInt з дробу. BigInt(1.5) кидає TypeError, спершу треба округлити: BigInt(Math.trunc(1.5)).
  • JSON.stringify() з BigInt у структурі. Кидає TypeError: Do not know how to serialize a BigInt, тому такі значення передають рядком: String(id).
  • Плутанина == і ===. 10n == 10 це true, але 10n === 10 це false, бо типи різні.
  • Виклик Math з BigInt. Math.max(1n, 2n) і Math.sqrt(4n) кидають TypeError.
  • Використання BigInt там, де він не потрібен. Він повільніший за Number і не підтримує дробів, тож для звичайних обчислень залишайте Number.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.