Произвольная точность BigInt в JavaScript

внешний интерфейс
Произвольная точность BigInt в JavaScript

Вас, как фронтенд-разработчика, когда-нибудь беспокоили большие целые числа? JavaScript никогда не поддерживал большие целые числа. Если вы хотите работать с большими целыми числами, вы должны использовать сторонние библиотеки. Помимо проблем, могут возникнуть проблемы с чрезмерной упаковкой и эффективностью времени выполнения. В отличие от Java, уже давно существует метод, который может представлять произвольную точность.BigInteger. А для JavaScript предложение в ECMAScriptBigIntэто новый числовой примитивный тип, который может представлять произвольную точность.

Эта статья в основном посвященаBigIntРасскажите о его статусе, функциях, прогрессе и текущем использовании.

Номерные типы ограничений

в JavaScriptNumberявляется типом с плавающей запятой двойной точности, что означает ограниченную точность.Number.MAX_SAFE_INTEGERОн находится в пределах максимальной безопасности для2**53-1. Минимальное безопасное значение равноNumber.MIN_SAFE_INTEGERзначение-((2**53)-1). Расчеты за пределами безопасных значений теряют точность. Как следует, вы можете видетьmax + 1а такжеmax + 2то же самое, что явно неправильно.

const max = Number.MAX_SAFE_INTEGER; // 9007199254740991
max + 1 // 9007199254740992
max + 2 // 9007199254740992

Что касается того, почему максимальное безопасное значение2**53-1С IEEE float плавающее хранилище 754 может быть указано по ссылкеХватай хвостик данных — ловушка JS и решение с плавающей запятой.

В практических применениях, например, в большом целочисленном идентификаторе, точность временной техники будет вызывать проблемы небезопасными.Twitter IDs (snowflake)performanceобъект сBigInt

// 1 毫秒(ms) = 1,000 微秒(μs) = 1,000,000 纳秒(ns) = 1,000,000,000 皮秒(ps)
const scale = 1000000000
const scaleBig = 1000000000n
const big = BigInt((performance.now() * scale).toFixed(0)) + BigInt(performance.timing.navigationStart) * scaleBig
const normal = (performance.now() + performance.timing.navigationStart) * scale
console.log(big) // 1550488515092440117252n 精确到皮秒
console.log(normal) // 1.550488515092455e+21 精确到微秒

在没有 BigInt 的时候,如果想要使用大整型,则不得不借助类似 BigInt 功能的第三方库。这有可能会影响 JavaScript 程序的效率,比如加载时间、解析时间、编译时间,以及运行时的效率。 На картинке нижеBigIntСравнение производительности с другими подобными сторонними библиотеками.

BigInt 与其他类似第三方库的性能对比

Особенности BigInt

BigInt— это новый примитивный тип, позволяющий выполнять вычисления с произвольной точностью. СоздайтеBigIntЗначение типа также очень простое, просто добавьте число после числаnВот и все. Например,789стали789n. Вы также можете использовать глобальные методыBigInt(value)Преобразование в цифровое эталонное значение или числовая строка. Например:

BigInt(1234567890) === 1234567890n // true

Другим примером является преобразование метки времени, описанное выше.

новый примитивный тип

теперь, когдаBigIntэто новый примитивный тип, то его можно использоватьtypeofопределить собственный тип

typeof 111 // "number"
typeof 111n // "bigint"

в то же времяBigIntа такжеNumberЗначения типов также не являются строго равными.

111 === 111n // false
111 == 111n // true

В логике между цифровыми логическими значениямиBigIntа такжеNumberСтабильная производительность.

if (0n) {
  console.log('if');
} else {
  console.log('else');
}
// → logs 'else', because `0n` is falsy.

если ты считаешьBigInt, количество примитивных типов в JavaScript изменилось с 6 до 7.

  • Boolean
  • Null
  • Undefined
  • Number
  • String
  • Symbol (new in ECMAScript 2015)
  • BigInt (new in future ECMAScript)

операция

BigIntПоддерживает наиболее часто используемые операторы,+, -, *, /, %, а также**.

|, &, <<, >>, ^производительность такжеNumberпоследовательный по типу.

унарный оператор-представляет собой отрицательное число, но+Не может использоваться для представления положительных чисел. Потому что в webAssembly (asm.js)+xвсегда означаетNumberили необычные обстоятельства.

Также нельзя смешиватьBigIntа такжеNumberРассчитайте, например, в следующем результате выброс исключение:

1 + 1n
// Uncaught TypeError: Cannot mix BigInt and other types, use explicit conversions

Так как их нельзя смешиватьBigIntа такжеNumber, вы не можете избавиться от необходимости помещать весь код вNumberиспользовать обаBigIntзаменять. Это зависит от ситуации, если число может стать очень большим, решите использоватьBigInt.

API

  • BigInt()Number()BigIntТипы.

    BigInt(1) // 1n
    BigInt(1.5) // RangeError
    BigInt('1.5') // SyntaxError
    
  • BIGINT64ARRAY и BIGUINT64ARRAY

    в то же времяBigInt64-битные целые числа со знаком и без знака также могут быть представлены точно, поэтому есть два новых TypedArray, а именно BigInt64Array и BigUint64Array.

    const view = new BigInt64Array(4);
    // → [0n, 0n, 0n, 0n]
    view.length;
    // → 4
    view[0];
    // → 0n
    view[0] = 42n;
    view[0];
    // → 42n
    

ECMAScript TC39 Прогресс

В настоящее время определены новые возможности ES2019, см.Twitter -New JavaScript features in ES2019Без BigInt, как показано ниже:

➡️ Array#{flat,flatMap}
➡️ Object.fromEntries
➡️ String#{trimStart,trimEnd}
➡️ Symbol#description
➡️ try { } catch {} // optional binding
➡️ JSON ⊂ ECMAScript
➡️ well-formed JSON.stringify
➡️ stable Array#sort
➡️ revised Function#toString

Также доступно на githubtc39 завершенный драфтвидел в.

BigIntв настоящее время вЭтап 3, если проблема не большая, ее надо включить в ES2020.

Поддержка и полифилл

В настоящее время (201902) поддержка браузеров не идеальна, только Chrome поддерживает лучше, а другие браузеры не поддерживают хорошо. В отличие от других новых функций JavaScript, BigInt плохо компилируется в ES5. Поскольку BigInt изменяет рабочее поведение операторов, это поведение не может быть напрямую преобразовано полифиллами.

Но можно использовать библиотекуthe JSBI libraryДля реализации Bigint. JSBI — это дизайн и реализация Bigint в V8 и Chrome, функция совместима с браузером, а синтаксис немного отличается:

import JSBI from './jsbi.mjs';

const max = JSBI.BigInt(Number.MAX_SAFE_INTEGER);
const two = JSBI.BigInt('2');
const result = JSBI.add(max, two);
console.log(result.toString());
// → '9007199254740993'

Как только BigInt станет встроенной поддержкой для всех браузеров, можно будет использовать плагины.babel-plugin-transform-jsbi-to-bigintУдалите JSBI в собственный синтаксис BigInt. Например, приведенный выше код преобразуется в:

const max = BigInt(Number.MAX_SAFE_INTEGER);
const two = 2n;
const result = max + two;
console.log(result);
// → '9007199254740993'

Поддержка TypeScript

Tymdercript 3.2 был добавленBigInttarget: esnextВот и все. Примеры использования следующие:

let foo: bigint = BigInt(100); // the BigInt function
let bar: bigint = 100n;        // a BigInt literal

// *Slaps roof of fibonacci function*
// This bad boy returns ints that can get *so* big!
function fibonacci(n: bigint) {
  let result = 1n;
  for (let last = 0n, i = 0n; i < n; i++) {
    const current = result;
    result += last;
    last = current;
  }
  return result;
}

fibonacci(10000n)

резюме

Если вы уверены, что ваша страница работает только в последней версии Chrome, смело используйте ее прямо сейчас.BigIntТеперь обрабатывайте большие данные более элегантно и эффективно. Если вам нужна поддержка в других браузерах, вы можете использоватьJSBIЭта библиотека, поза скинуть ее в будущем, тоже очень элегантна.

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

Ссылаться на