29 серпня 2024 р.

BigInt

Нещодавнє доповнення
Це нещодавнє доповнення до мови. Поточний стан підтримки можна знайти на сторінці https://caniuse.com/#feat=bigint.

BigInt – це спеціальний числовий тип, який забезпечує підтримку цілих чисел довільної довжини.

Bigint створюється шляхом додавання n до кінця цілочисельного літералу або викликом функції BigInt, яка створює великі числа з рядків, чисел тощо.

const bigint = 1234567890123456789012345678901234567890n;

const sameBigint = BigInt("1234567890123456789012345678901234567890");

const bigintFromNumber = BigInt(10); // те саме що і 10n

Математичні оператори

BigInt можна використовувати як звичайне число, наприклад:

alert(1n + 2n); // 3

alert(5n / 2n); // 2

Зверніть увагу: поділ 5/2 повертає результат, округлений до нуля, без десяткової частини. Усі операції над великими числами повертають великі числа.

Ми не можемо змішувати великі та звичайні числа:

alert(1n + 2); // Error: Cannot mix BigInt and other types

Ми повинні явно конвертувати їх, якщо потрібно: використовуючи BigInt() або Number(), наприклад:

let bigint = 1n;
let number = 2;

// число у велике число
alert(bigint + BigInt(number)); // 3

// велике число у число
alert(Number(bigint) + number); // 3

Операції перетворення завжди безшумні, ніколи не дають помилок, але якщо величе число занадто велике і не відповідає типу числа, то зайві біти будуть відрізані, тому ми повинні бути обережними, виконуючи таке перетворення.

Унарний плюс не підтримується на великих числах

Оператор унарний плюс +value є добре відомим способом перетворення value у число.

Щоб уникнути плутанини, він не підтримується на великих числах:

let bigint = 1n;

alert( +bigint ); // помилка

Тому ми повинні використовувати Number(), щоб перетворити велике число в число.

Порівняння

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

alert( 2n > 1n ); // true

alert( 2n > 1 ); // true

Зверніть увагу, оскільки числа та великі числа мають різні типи, вони можуть бути рівними ==, але не строго рівними ===:

alert( 1 == 1n ); // true

alert( 1 === 1n ); // false

Булеві операції

Всередині if або інших логічних операцій великі числа поводяться як числа.

Наприклад, у if величе число 0n є хибним, інші значення є істинними:

if (0n) {
  // ніколи не виконається
}

Логічні оператори, такі як ||, && та інші також працюють з великими числами, подібно до чисел:

alert( 1n || 2 ); // 1 (1n вважається істинним)

alert( 0n || 2 ); // 2 (0n вважається хибним)

Поліфіли

Поліфілення великих чисел є складним. Причина в тому, що багато операторів в JavaScript, таких як +, - тощо, поводяться по-різному з великими числами порівняно зі звичайними числами.

Наприклад, поділ великих чисел завжди повертає велике число (за потреби округляється).

Щоб емулювати таку поведінку, поліфіл має проаналізувати код і замінити всі такі оператори своїми функціями. Але це громіздко і буде коштувати великої жертви в продуктивності.

Отже, добре відомого хорошого поліфілу не існує.

Проте, розробники бібліотеки JSBI пропонують рішення.

Ця бібліотека реалізує підтримку великих чисел, використовуючи власні методи. Ми можемо використовувати їх замість нативних великих чисел:

Операція нативний BigInt JSBI
Створення from Number a = BigInt(789) a = JSBI.BigInt(789)
Додавання c = a + b c = JSBI.add(a, b)
Віднімання c = a - b c = JSBI.subtract(a, b)

…А потім скористайтеся поліфілом (плагін для Babel), щоб перетворити виклики JSBI на нативні великі числа для тих браузерів, які їх підтримують.

Іншими словами, цей підхід припускає, що ми пишемо код на JSBI замість нативних великих чисел. Але JSBI всередині працює з числами як із великими числами, емулює їх відповідно до специфікації, тож код буде «готовий до великих чисел».

Ми можемо використовувати такий код JSBI «як є» для двигунців, які не підтримують великі числа, а для тих, які підтримують – поліфіл конвертуватиме виклики в нативні великі числа.

Посилання

Навчальна карта