121 lines
3.6 KiB
Markdown
121 lines
3.6 KiB
Markdown
由于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 |