BigInt — новый тип данных в JS
На днях, я обновил chrome до 67-й версии, и оказалось в нем теперь есть поддержка примитивного типа — BigInt. Технология находится в третьей стадии / черновик. Давайте вместе посмотрим что это такое и где это может пригодиться.
Проблема
До текущего момента, все числа, и целые и дробные были представлены одним типом Number, так же имеющим название “double-precision floats”. Если не вникать в подробности, то это означает, что этот тип имеет ограниченную точность. Константа Number.MAX_SAFE_INTEGER хранит максимально возможное целое число, которое можно безопасно увеличивать. Его значение равно двум в пятдесят третьей степени, минус один (2**53–1).
Попробуем сложить максимальное число и единицу. Результат верный — число больше на единицу.
Но при сложении с двойкой, JS выдает ошибочный результат, в нашем случае такой же как и предыдущий.
Проблема, думаю, видна. Все расчеты, вне диапазона от Number.MIN_SAFE_INTEGER до Number.MAX_SAFE_INTEGER, могут быть неточными.
BigInt
BigInt — новый числовой примитив, который позволяет использовать большие числа с высокой точностью.
Чтобы создать BigInt, добавьте суффикс n в любой целочисленный литерал. Например, 123 становится 123n. Глобальную функцию BigInt можно использовать для преобразования обычного числа в BigInt. Другими словами, BigInt (123) === 123n. Теперь решим нашу проблему используя BigInt.
Вот еще один пример, где мы умножаем два числа с типом Number:
Мы знаем, что результат умножения должен заканчиваться на 7 (так как последние цыфры в числах 9 и 3, 9 * 3 === 27 ). Однако результат заканчивается набором нулей. Повторим то жесамое с BigInts:
И снова, с BigInt, ответ верный.
Безопасные пределы (Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER) не применяются к BigInts. Мы можем спокойно выполнять целочисленную арифметику , не беспокоясь о потере точности.
Новый примитив
BigInt — новый примитив в языке JavaScript. Тип BigInt может быть определен с помощью оператора typeof:
BigInt — это отдельный тип, и по этому при строгом сравнении (===) с Number мы увидим false. Прежде чем выполнять строгое сравнение (без приведения типов) BigInt с Number, нужно преобразовать один из них в тип другого.
При принуждении к логическому (что происходит при использовании if, &&, || или Boolean (int), например), BigInts следуют той же логике, что и Numbers.
Если необходимо привести BigInt к логическому типу (что происходит при использовании if, &&, ||, Boolean(int) ), то новый тип ведет себя подобно типу Number:
asm.js
Прежде чем мы пойдем дальше нужно немного затронуть asm.js (хоть и сам столкнулся впервые), ведь новый тип чисел тесно связан с этой реализацией языка.
asm.js это оптимизированное низкоуровневое подмножество JavaScript. И если попытаться еще проще — это некий низкоуровневый синтаксис, с доступом к памяти, подобный c или c++, в основном предназначенный для работы с арифметикой. После компиляции мы получаем очень оптимизированный js код.
Разработчики новых реализаций JS заимствуют решения из asm.js и пытаются поддерживать совместимость. Asm.js это огромная тема и довольно сложная, но может когда то и осилю и ее.
Операторы
BigInt поддерживает наиболее распространенные операторы. Двоичные +, -, * и ** работают как и ожидается. / и % работают и округляют до нуля по мере необходимости. Побитовые операции |, &, > и ^ выполняют поразрядную арифметику, при условии представления two’s complement representation для отрицательных значений, как и для Number.
Унарный минус (-) может использоваться для обозначения отрицательного значения BigInt, например -42n. Унарный плюс (+)не поддерживается, потому что он нарушит код asm.js , который ожидает, что конструкция вида +x всегда будет возвращать либо Number, либо выбрасывать исключение.
Так же, нельзя смешивать операции между BigInts и Numbers. Это хорошо, потому что любое неявное преобразование может потерять часть информации. Рассмотрим пример:
Что увидим в результате? Здесь нет и не может быть правильного ответа. Если предположить, что движок попытается привести типы, то все равно, BigInt не может содержать дробные числа, а Number не может отобразить точное число выше безопасного. Поэтому такие операции приведут к выбросу исключения TypeError.
Есть только одно исключение — это операторы сравнения, такие как ===, и >=, так как они возвращают одно из двух логических значений, и не рискуют точностью.
Доступно несколько новых API методов BigInt.
Конструктор BigInt похож на конструктор Number: он преобразует свой аргумент в тип BigInt. Если преобразование невозможно, будет выброшено исключение SyntaxError или RangeError.
Функции утилиты
BigInt.parseInt(string, radix?) — Работает аналогично Number.parseInt (), но выдает SyntaxError вместо возврата NaN в случае невозможности вычислить значение.
Так же есть возможность ограничивать число по битам, BigInt.asUint и NBigInt.asInt. Их я описывать не буду, это связано с побитовыми операциями. Если интересно — вот спека.
Отзывы
Уже есть замечания по производительности. В любом случае — BigInt еще черновик.
Вывод
Я думаю этот тип данных будет довольно редок в использовании. Очень редкий кейс, считать такие астрономические значения, но и удивляться не стоит встретив в коде значение, например, 120n — это просто BigInt.
Я надеюсь, вам понравился пост. Если да, похлопайте , чтобы помочь другим найти эту информацию. И не стесняйтесь оставлять комментарии — буду рад любым замечаниям!
BigInt
BigInt это встроенный объект, который предоставляет способ представлять целые числа больше 253 — 1, наибольшего числа, которое JavaScript может надёжно представить с Number примитивом. Это максимальное значение можно получить, обратившись к Number.MAX_SAFE_INTEGER .
Описание
BigInt создаётся путём добавления n в конец целочисленного литерала — 10n — или вызовом функции BigInt() .
const theBiggestInt = 9007199254740991n; const alsoHuge = BigInt(9007199254740991); // ↪ 9007199254740991n const hugeString = BigInt("9007199254740991"); // ↪ 9007199254740991n const hugeHex = BigInt("0x1fffffffffffff"); // ↪ 9007199254740991n const hugeBin = BigInt( "0b11111111111111111111111111111111111111111111111111111", ); // ↪ 9007199254740991n
В некотором смысле он похож на Number , но отличается в некоторых ключевых моментах — его нельзя использовать с методами во встроенном объекте Math и нельзя смешивать в операциях с любыми экземплярами Number.
Предупреждение: Number и BigInt нельзя смешивать в операциях — они должны быть приведены к тому же типу.
Будьте осторожны приводя значения туда и обратно, так как точность BigInt может быть потеряна при приведении к числу ( Number) .
Тип
При проверке с использованием оператора typeof , BigInt выдаёт тип «bigint» :
typeof 1n === "bigint"; // true typeof BigInt("1") === "bigint"; // true
При оборачивании в объект, BigInt будет представлен как обычный объект:
typeof Object(1n) === "object"; // true
Операторы
Следующие операторы могут использоваться с BigInt (или объектом-обёрткой BigInt ): + , * , — , ** , % .
Побитовые операции (en-US) также поддерживаются, кроме >>> (сдвиг вправо с заполнением нулями).
Не поддерживаемый унарный оператор ( + ) больше не ломает asm.js.
const previousMaxSafe = BigInt(Number.MAX_SAFE_INTEGER); // ↪ 9007199254740991n const maxPlusOne = previousMaxSafe + 1n; // ↪ 9007199254740992n const theFuture = previousMaxSafe + 2n; // ↪ 9007199254740993n, это работает! const multi = previousMaxSafe * 2n; // ↪ 18014398509481982n const subtr = multi – 10n; // ↪ 18014398509481972n const mod = multi % 10n; // ↪ 2n const bigN = 2n ** 54n; // ↪ 18014398509481984n bigN * -1n // ↪ –18014398509481984n
Оператор / также работает, как и ожидалось, с целыми числами. Однако, поскольку это BigInt, эта операция будет округляться в меньшую сторону, то есть она не будет возвращать какие-либо дробные цифры.
Предупреждение: Результат операции с дробным результатом будет округлён в меньшую сторону при использовании BigInt .
const expected = 4n / 2n; // ↪ 2n const rounded = 5n / 2n; // ↪ 2n, not 2.5n
Сравнения
BigInt равен Number только при нестрогом сравнении.
0n === 0; // ↪ false 0n == 0; // ↪ true
Обычные числа и BigInt можно сравнивать как обычно.
1n 2; // ↪ true 2n > 1; // ↪ true 2 > 2; // ↪ false 2n > 2; // ↪ false 2n >= 2; // ↪ true
Они могут быть смешаны в массивах и отсортированы:
const mixed = [4n, 6, -12n, 10, 4, 0, 0n]; // ↪ [4n, 6, -12n, 10, 4, 0, 0n] mixed.sort(); // ↪ [-12n, 0, 0n, 10, 4n, 4, 6]
Обратите внимание, что сравнения с обьектом -обёрткой BigInt действуют как с другими объектами, указывая на равенство только когда сравнивается идентичный экземпляр объекта:
0n === Object(0n); // false Object(0n) === Object(0n); // false const o = Object(0n); o === o; // true
Условные выражения
BigInt ведёт себя как обычное число в следующих случаях:
- Преобразуется в Boolean через функцию Boolean
- Используется с логическими операторами Logical Operators (en-US) || , && и !
- В условном тесте, таком как if statement .
if (0n) console.log("Привет из if!"); > else console.log("Привет из else!"); > // ↪ "Привет из else!" 0n || 12n; // ↪ 12n 0n && 12n; // ↪ 0n Boolean(0n); // ↪ false Boolean(12n); // ↪ true !12n; // ↪ false !0n; // ↪ true
Конструктор
Статические методы
Оборачивает BigInt в пределах от -2width-1 до 2width-1-1
Оборачивает a BigInt в пределах от 0 до 2width-1
Методы экземпляра
Возвращает строку с языкозависимым представлением числа. Переопределяет метод Object.prototype.toLocaleString() .
Возвращает строку, представляющую указанный объект по указанному основанию системы счисления. Переопределяет метод Object.prototype.toString() .
Возвращает примитивное значение указанного объекта. Переопределяет метод Object.prototype.valueOf() .
Рекомендации по использованию
Приведение
Поскольку приведение между Number и BigInt может привести к потере точности, рекомендуется использовать BigInt только тогда, когда разумно ожидаются значения, превышающие 253 и не приводить между двумя типами.
Криптография
Операции поддерживаемые BigInt не постоянны во времени. BigInt следовательно не пригоден для использования в криптографии.
Использование вместе с JSON
Использование JSON.stringify() с любым значением типа BigInt приведёт к TypeError , поскольку значения BigInt не преобразуется в JSON по умолчанию, однако вы можете реализовать свой собственный метод toJSON , если вам необходимо:
BigInt.prototype.toJSON = function () return this.toString(); >;
Теперь вместо ошибки, JSON.stringify будет создавать строку:
JSON.stringify(BigInt(1)); // '"1"'
Примеры
Расчёт простых чисел
// Возвращает true, если BigInt — простое число function isPrime(p) for (let i = 2n; i * i p; i++) if (p % i === 0n) return false; > return true; > // Берет BigInt в качестве аргумента и возвращает BigInt function nthPrime(nth) let maybePrime = 2n; let prime = 0n; while (nth >= 0n) if (isPrime(maybePrime)) nth--; prime = maybePrime; > maybePrime++; > return prime; > nthPrime(20n); // ↪ 73n
Спецификации
Specification |
---|
ECMAScript Language Specification # sec-bigint-objects |
Совместимость браузера
BCD tables only load in the browser
Смотрите также
- Number
- Number.MAX_SAFE_INTEGER
Found a content problem with this page?
- Edit the page on GitHub.
- Report the content issue.
- View the source on GitHub.
This page was last modified on 4 авг. 2023 г. by MDN contributors.
Your blueprint for a better internet.
Большое целое
В математике числа бесконечны, а в программировании — нет. Если число не влезает в стандартный number , то есть его старший брат.
Время чтения: меньше 5 мин
Это незавершённая статья. Вы можете помочь её закончить! Почитайте о том, как контрибьютить в Доку.
Открыть/закрыть навигацию по статье
Обновлено 19 июля 2022
Кратко
Скопировать ссылку «Кратко» Скопировано
Тип большого целого Big Int — примитивный тип, который представляет целые числа больше 2 53 -1. Эти числа уже не помещаются в стандартный примитив «число».
Этот тип может использоваться для работы с произвольно большими целыми числами.
Как пишется
Скопировать ссылку «Как пишется» Скопировано
Создать Big Int можно двумя способами.
1️⃣ Добавить суффикс n в конец записи числа:
const biggy = 9997000254740991n
const biggy = 9997000254740991n
2️⃣ Вызвать конструктор Big Int :
const alsoBig = BigInt(9997000254999999)
const alsoBig = BigInt(9997000254999999)
Для Big Int определены операции сложения + , вычитания — , умножения * , взятия остатка от деления % , возведение в степень ** .
Операция деления / также работает, но дробная часть будет отброшена:
const seven = 7nconst five = 5n console.log(seven / five)// 1
const seven = 7n const five = 5n console.log(seven / five) // 1
Big Int не сериализуется в JSON. Это усложняет использование этого типа данных в задачах взаимодействия с сервером.
JavaScript BigInt
JavaScript BigInt variables are used to store big integer values that are too big to be represented by a normal JavaScript Number .
JavaScript Integer Accuracy
JavaScript integers are only accurate up to 15 digits:
Integer Precision
let x = 999999999999999;
let y = 9999999999999999;
In JavaScript, all numbers are stored in a 64-bit floating-point format (IEEE 754 standard).
With this standard, large integer cannot be exactly represented and will be rounded.
Because of this, JavaScript can only safely represent integers:
Up to 9007199254740991 +(2 53 -1)
Down to -9007199254740991 -(2 53 -1).
Integer values outside this range lose precision.
How to Create a BigInt
To create a BigInt , append n to the end of an integer or call BigInt() :
Examples
let x = 9999999999999999;
let y = 9999999999999999n;
let x = 1234567890123456789012345n;
let y = BigInt(1234567890123456789012345)
BigInt: A new JavaScript Datatype
The JavaScript typeof a BigInt is «bigint»:
Example
let x = BigInt(999999999999999);
let type = typeof x;
BigInt is the second numeric data type in JavaScript (after Number ).
With BigInt the total number of supported data types in JavaScript is 8:
1. String
2. Number
3. Bigint
4. Boolean
5. Undefined
6. Null
7. Symbol
8. Object
BigInt Operators
Operators that can be used on a JavaScript Number can also be used on a BigInt .
BigInt Multiplication Example
let x = 9007199254740995n;
let y = 9007199254740995n;
let z = x * y;
Notes
Arithmetic between a BigInt and a Number is not allowed (type conversion lose information).
Unsigned right shift (>>>) can not be done on a BigInt (it does not have a fixed width).
BigInt Decimals
A BigInt can not have decimals.
BigInt Division Example
let x = 5n;
let y = x / 2;
// Error: Cannot mix BigInt and other types, use explicit conversion.
let x = 5n;
let y = Number(x) / 2;
BigInt Hex, Octal and Binary
BigInt can also be written in hexadecimal, octal, or binary notation:
BigInt Hex Example
let hex = 0x20000000000003n;
let oct = 0o400000000000000003n;
let bin = 0b100000000000000000000000000000000000000000000000000011n;
Precision Curiosity
Rounding can compromise program security:
MAX_SAFE_INTEGER Example
9007199254740992 === 9007199254740993; // is true .
Browser Support
BigInt is supported in all browsers since September 2020:
Chrome 67 | Edge 79 | Firefox 68 | Safari 14 | Opera 54 |
May 2018 | Jan 2020 | Jul 2019 | Sep 2020 | Jun 2018 |
Minimum and Maximum Safe Integers
ES6 added max and min properties to the Number object:
- MAX_SAFE_INTEGER
- MIN_SAFE_INTEGER
MAX_SAFE_INTEGER Example
let x = Number.MAX_SAFE_INTEGER;
MIN_SAFE_INTEGER Example
let x = Number.MIN_SAFE_INTEGER;
New Number Methods
ES6 also added 2 new methods to the Number object:
- Number.isInteger()
- Number.isSafeInteger()
The Number.isInteger() Method
The Number.isInteger() method returns true if the argument is an integer.
Example: isInteger()
Number.isInteger(10);
Number.isInteger(10.5);
The Number.isSafeInteger() Method
A safe integer is an integer that can be exactly represented as a double precision number.
The Number.isSafeInteger() method returns true if the argument is a safe integer.
Example isSafeInteger()
Number.isSafeInteger(10);
Number.isSafeInteger(12345678901234567890);
Safe integers are all integers from -(2 53 — 1) to +(2 53 — 1).
This is safe: 9007199254740991. This is not safe: 9007199254740992.