js-BigInt基本數據類型


BigInt 可能會成為自 ES2015 引入 Symbol 之后,增加的第一個新的內置類型。並且 BigInt 類型在 TypeScript3.2 版本被內置。。。本篇將簡單記錄下BigInt

js 采用雙精度浮點數,這也導致了精度有限的問題。在 js 中,Number 基本類型可以精確表示的最大整數是 2^53。因此早期會有這如下的“bug”:

let max = Number.MAX_SAFE_INTEGER;    // 最大安全整數

let max1 = max + 1
let max2 = max + 2

max1 === max2 //true

為了解決這個限制,BigInt出現在了ECMAScript標准中。

let max = BigInt(Number.MAX_SAFE_INTEGER);

let max1 = max + 1n
let max2 = max + 2n

max1 === max2 // false

介紹

BigInt 可以表示任意大的整數。

創建

語法:

BigInt(value);

其中參數:

  value: 創建對象的數值。可以是字符串或者整數。

注意, BigInt() 不是構造函數,因此不能使用 new 操作符。

除了通過BigInt構造函數,我們還可以通過在一個整數字面量后面加 n 的方式定義一個 BigInt ,如:10n

例:

let valA = 10n;
let valB = BigInt(10);

console.log(valA === valB);     // true

類型判斷

我們可以通過typeof操作符來判斷是否為BigInt類型(返回字符串"bigint"),如

typeof 1n === 'bigint'; // true
typeof BigInt('1') === 'bigint'; // true

同樣的,我們也可以用最通用的Object.prototype.toString方法(返回字符串"[object BigInt]"

Object.prototype.toString.call(10n) === '[object BigInt]';    // true

運算

以下操作符可以和 BigInt 一起使用: +*-**% 。除 >>> (無符號右移)之外的 位操作 也可以支持。(因為 BigInt 都是有符號的 >>> (無符號右移)不能用於 BigInt)。

為了兼容 asm.js ,.BigInt 不支持單目 (+) 運算符。

const previousMaxSafe = BigInt(Number.MAX_SAFE_INTEGER);
// 9007199254740991n

const maxPlusOne = previousMaxSafe + 1n;
// 9007199254740992n
 
const theFuture = previousMaxSafe + 2n;
// 9007199254740993n, this works now!

const multi = previousMaxSafe * 2n;
// 18014398509481982n

const subtr = multi – 10n;
// 18014398509481972n

const mod = multi % 10n;
// 2n

const bigN = 2n ** 54n;
// 18014398509481984n

bigN * -1n
// –18014398509481984n

當使用 BigInt 時,帶小數的運算會被取整。

const expected = 4n / 2n;
// 2n

const rounded = 5n / 2n;
// 2n, not 2.5n

方法

BigInt.asIntN()

將 BigInt 值轉換為一個 -2^width - 1 與 2^(width-1) - 1 之間的有符號整數。

語法:

BigInt.asIntN(width, bigint);

如:

const max = 2n ** 64n - 1n;

BigInt.asUintN(64, max);
// 18446744073709551615n

BigInt.asUintN(64, max + 1n);
// 0n
// zero because of overflow

BigInt.asUintN()

將一個 BigInt 值轉換為 0 與 2^width-1 之間的無符號整數。

語法:

BigInt.asUintN(width, bigint);
const max = 2n ** 64n - 1n;

BigInt.asUintN(64, max);
// 18446744073709551615n

BigInt.asUintN(64, max + 1n);
// 0n
// zero because of overflow

BigInt和Number

BigInt 和 Number 不是嚴格相等的,但是寬松相等的。

10n === 10
// false

10n == 10
// true

Number 和 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 在需要轉換成 Boolean 的時表現跟 Number 類似:如通過 Boolean 函數轉換;用於 Logical Operators ||, &&, 和 ! 的操作數;或者用於在像 if statement 這樣的條件語句中。

它在某些方面類似於 Number ,但是也有幾個關鍵的不同點:不能用與 Math 對象中的方法;不能和任何 Number 實例混合運算,兩者必須轉換成同一種類型。在兩種類型來回轉換時要小心,因為 BigInt 變量在轉換成 Number 變量時可能會丟失精度。

不允許隱式類型轉換

因為隱式類型轉換可能丟失信息,所以不允許在bigint和 Number 之間進行混合操作。當混合使用大整數和浮點數時,結果值可能無法由BigInt或Number精確表示。

如:

10n + 1;    // Uncaught TypeError: Cannot mix BigInt and other types, use explicit conversions
Math.max(2n, 4n, 6n);    // TypeError...

BigInt和String

難免會遇到數字和字符串的轉換,BigInt也不例外,不過可惜的是BigInt轉為String時,其標志性的n會被省略,如

String(10n);    // '10'
'' + 11n;    // '11'

因此也導致以下情況:

// array
let arr = [1, 2, 3, 4, 5];

arr[2] === arr[2n];    // true

// object
let obj = {
    '1': '1',
    '2': '2',
    '3': '3',
    '4': '4'
};

obj['1'] === obj[1n];        // true

零值

BigInt 沒有 Number 的正零(+0)和負零(-0)之分。因為 BigInt 表示的是整數

無窮和NaN判斷

很有趣的現象

isFinite(10n);    // Uncaught TypeError: Cannot convert a BigInt value to a number
Number.isFinite(10n);    // false

isNaN(10n);    // Uncaught TypeError: Cannot convert a BigInt value to a number
Number.isNaN(10n);    // false

由此我們可以看出isFinite()和Number.isFinite()、isNaN()和Number.isNaN()的區別:isFinite(val)/isNaN(val)的工作機制都是講參數值val轉為數值后再進行比較判斷,而Number.isFinite(val)/Number.isNaN(val)則可以理解為直接簡單粗暴的變量全等判斷(val === Infinity/val === NaN

兼容

如圖,兼容情況並不是很好。並且轉換BigInt是一個極其復雜的過程,這會導致嚴重的運行時性能損失。直接polyfill BigInt也是不可能的,因為該提議改變了幾個現有操作符的行為。目前,更好的選擇是使用JSBI庫,它是BigInt提案的純JS實現,訪問地址>>

使用如下:

import JSBI from './jsbi.mjs';

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

TypeScript

BigInt 類型在 TypeScript3.2 版本被內置,

在TypeScript中,BigInt 和 Number 都是有表示數字的意思,但是實際上兩者類型是不同的:

declare let valA: number;
declare let valB: bigint;

valA = valB; // error: Type 'bigint' is not assignable to type 'number'.
valB = valA; // error: Type 'number' is not assignable to type 'bigint'.

除了類型定義,TypeScript 中 BigInt 其他使用方法同 ES。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM