BigInt проти Number
BigInt це спеціальний числовий тип JavaScript, який дозволяє працювати з цілими числами довільної довжини, без обмеження 2^53 - 1. Значення створюється додаванням n у кінці числа або викликом функції BigInt().
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().
Швидкий приклад
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-бітне число з рухомою крапкою). Це означає, що мова може точно представляти цілі числа лише до:
Number.MAX_SAFE_INTEGER === 9007199254740991; // 2^53 - 1Якщо число більше, починається втрата точності:
const num = 9007199254740991;
console.log(num + 1); // 9007199254740992, коректно
console.log(num + 2); // 9007199254740992, помилкаЧисла «злиплися»: рушій уже не може відрізнити
+1від+2, бо сусідні цілі в цьому діапазоні не мають окремого представлення.
BigInt вирішує саме цю проблему:
const big = 9007199254740991n;
console.log(big + 1n); // 9007199254740992n
console.log(big + 2n); // 9007199254740993n, точноЯк створити BigInt
Є три способи, і жоден з них не приймає дробів:
const a = 10n; // літерал
const b = BigInt(10); // через функцію
const c = BigInt("9007199254740995"); // з рядкаBigInt(1.5); // TypeError: Cannot convert 1.5 to a BigIntАрифметика з BigInt
Підтримуються базові операції, але всі вони цілочисельні:
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 не можна змішувати в одному арифметичному виразі:
const big = 10n;
const num = 5;
console.log(big + num); // TypeError: Cannot mix BigInt and other typesПотрібне явне приведення типу:
console.log(big + BigInt(num)); // 15n
// або
console.log(Number(big) + num); // 15Порівняння, на відміну від арифметики, працює: при нестрогому порівнянні тип приводиться автоматично.
10n == 10; // true, нестроге порівняння
10n === 10; // false, строге порівняння, типи різні
10n < 20; // trueФункції Math з BigInt несумісні:
Math.sqrt(4n); // TypeError: Cannot convert a BigInt value to a numberЗа потреби значення спочатку приводять: Math.sqrt(Number(4n)), пам'ятаючи, що на дуже великих числах таке приведення знову втратить точність.
Number проти BigInt
| Особливість | Number | BigInt |
|---|---|---|
| Тип | число з рухомою крапкою | ціле число довільної довжини |
| Максимальна точність | до 2^53 - 1 | необмежена |
| Підтримка дробів | так | ні |
| Операції | стандартні | стандартні, але тільки цілочисельні |
| Сумісність | скрізь | з 2020 року |
Використання з JSON | так | ні, JSON.stringify() кидає помилку |
| Приведення типів | сумісний з усім | треба приводити явно |
| Коли брати | звичайні числа і дроби | дуже великі цілі |
Де застосовують BigInt
Зберігання великих ідентифікаторів, наприклад з бази даних, де 64-бітний id не вміщується в безпечний діапазон Number:
const userId = 183748917238479182374981273n;Криптографія, блокчейн і фінанси, де округлення неприпустиме:
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.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.