学习下新增的BigInt类型

652 阅读3分钟

这是我参与11月更文挑战的第24天,活动详情查看:2021最后一次更文挑战

问题

面试官:你能讲讲es6新增的BigInt类型吗?

面试者:可以,这个主要是用来解决js超出最大精度后不准的问题。

面试官:js最大精度是多少?为什么不准?

面试者:巴拉巴拉小魔仙。。。

面试官:好的,你被录取了

以上场景纯属虚构哈。

今天来学学新增的BigInt类型。

BigInt

之前我们讲了js的精度问题,因为我们尾数部分只有52位,再加上隐藏的整数位,所以总共有53位。

然后最大精度的整数是Math.pow(2, 53) - 1, 超过的话js就不能保证准确了,比如:

Math.pow(2, 53) === Math.pow(2, 53) + 1  // true
console.log(90071992547409998) //  90071992547410000

定义

为了能准确表示最大精度以外的数,es6新增了BigInt类型,直译过来就是大整数

BigInt的写法是数字后面再加上n。它的数据类型是bigint

注意:只有整数才能加n。小数会报错。同时不能直接带+

var num = 123n
typeof num // 'bigint'

90071992547409998n // 90071992547409998n

console.log(0.1n) // error: Invalid or unexpected token
console.log(+1n) // error: Cannot convert a BigInt value to a number

它可以直接进行运算(加法,乘法,减法,除法等)

注意:除法运算,如果结果有小数,会被舍弃小数部分。

var num = 3n
var num1 = 2n
console.log(num + num1) // 5n
console.log(num * num1) // 6n
console.log(num / num1) // 1n

BigInt函数

全局提供了一个BigInt函数,可以方便把其它类型转成BigInt类型。

console.log(BigInt(123))  // 123n
console.log(BigInt(true)) // 1n
console.log(BigInt('123')) // 123n

参数必填,而且参数必须是可以转成数字的,不然会报错。

console.log(BigInt('aaa'))  // error: Cannot convert aaa to a BigInt
console.log(BigInt(undefined)) // error
console.log(BigInt(null)) // error
console.log(BigInt()) // error

它有2个静态方法

BigInt.asUintN(width, bigInt)

把给定的bigInt转成范围在0 到 2^width -1的bigInt值。如果bigInt不在这个范围则不能正确返回。

var num = 2n ** 64n
console.log(BigInt.asUintN(64, num - 1n)) // 18446744073709551615n

console.log(BigInt.asUintN(64, num)) // 0n

console.log(BigInt.asUintN(64,  -1n)) // 18446744073709551615n

BigInt.asIntN(width, bigInt)

把给定的bigInt转成范围在 -2^(width -1)到 2^(width -1)-1的bigInt值。如果bigInt不在这个范围则不能正确返回。

console.log(BigInt.asIntN(64,  -1n)) // -1n

var num = 2n ** (64n -1n)
console.log(BigInt.asIntN(64, num - 1n)) // 9223372036854775807n

console.log(BigInt.asIntN(64, num)) // -9223372036854775808n

其它

bigInt也可以转化其它类型

'' + 1n // "1"
String(1n) // "1"
Number(1n) //  1
Boolean(1n) // true

if语句也会转成对应的布尔型。

if(1n)  // true
if(0n)  // false

如果后台返回的数据已经超出最大安全整数,需要后台先把它转成bigInt类型再返回,不然我们拿到的时候已经是不准确的数值了。

参考

BigInt 数据类型