由于JS存在数值限制,整数范围是[-2^53, 2^53],在这个范围之外就是失真,看一个例子: ```javascript console.log(Math.pow(2, 53));//9007199254740992 console.log(Math.pow(2,53) + 1);//9007199254740992 console.log(-Math.pow(2, 53));//-9007199254740992 console.log(-Math.pow(2, 53) - 1);//-9007199254740992 ``` 可以看到`2^53+1`应该输出的是`9007199254740993`,但是由于数值超过了JS的整数限制,造成了数值溢出。负数也是同样的原因。 这种性质无疑会对大数运算带来一定的阻碍,像常见的斐波那契数列和阶乘,随着参数的增大,计算结果在某个阀值就会溢出,因此这就使得JS无法进行金融和科技上的精密计算。 ES2020 引入了一种新的数据类型 BigInt(大整数),这是 ECMAScript 的第八种数据类型。BigInt 只用来表示整数,没有位数的限制,任何位数的整数都可以`精确`表示。 来看一个实例: ```javascript var x = 123456789; var y = 987654321; console.log(x*y);//121932631112635260 ``` 即使不用检验,也可以看出,结果显然不正确,因为x与y个位数相乘得到的是9,而结果的末尾是0。 那么使用BigInt后呢? ```javascript var x = 123456789n; var y = 987654321n; console.log(x*y);//121932631112635269n ``` 得到的结果是正确的,感兴趣的话可以用字符串模拟乘法运算法则检验一下。 可以看到BigInt与Number的区别在于后缀n,那么在刷题过程中,可以通过toString()的方法,把n去掉。 ```javascript var x = 123456789n; var y = 987654321n; console.log(x*y);//121932631112635269n console.log((x*y).toString());//121932631112635269 ``` 因此BigInt值与Number值并不是同一类型: ```javascript var a = 11n; var b = 11; console.log(typeof a);//bigint console.log(typeof b);//number console.log(a === b)//false ``` 但是在一些语法上是相似的: 1. 能够接受其他进制的数值,并转为十进制: ```javascript console.log(Number(0b11));//3 console.log(BigInt(0b11n));//3n console.log(Number(0o71));//57 console.log(BigInt(0o71n));//57n console.log(Number(0xA));//10 console.log(BigInt(0xAn));//10n ``` 当然,使用BigInt进行转换时,也可以省略后缀n,**但是不推荐这样做**。 ```javascript console.log(BigInt(0b11));//3n ``` 2. 使用一元运算符进行简单的计算: ```javascript var x = 6n; var y = 4n; console.log(x + y);//10n console.log(x - y);//2n console.log(x * y);//24n console.log(x / y);//1n console.log(x % y);//2n ``` ```javascript var x = 6; var y = 4; console.log(x + y);//10 console.log(x - y);//2 console.log(x * y);//24 console.log(x / y);//1.5 console.log(x % y);//2 ``` 不同之处就是整除了,BigInt会返回整数,像C的整除一样,但是JS的整除返回的是在精度范围内的数字,也可以借助这一点来实现一些需求,例如在获取一个整数每位上的数字运算中,就可以现将这个这个整数转为BigInt类型,然后再计算,这样就省略了过程中借助`parseInt()`的转化了,来看一个例子: ```javascript var num = 123456789; var sum = 0; while(num){ sum += num%10; num = parseInt(num/10); } console.log(sum); ``` ```javascript var num = 123456789; num = BigInt(num); var sum = 0n; while(num != 0n){ sum += num % 10n; num = num/10n; } console.log(sum); ``` 好吧,虽然在这个例子中看起来很蠢,但是在一些条件下,确实可以起到很有效的作用。 需要注意的是,BigInt与Number进行运算时,会报错: ```javascript console.log(1 + 2n); ``` > TypeError: Cannot mix BigInt and other types, use explicit conversions