JavaScript 所有数字内部都是 float64 类型,所以数值的精度最多只能到 53 个二进制位,大于这个范围的整数是无法精确表示的。
在很多金融场景如果使用 JS 的话就得使用一些 BigNumber 库。其中以太坊 web3.js 使用的是最为流行的是 bignumber.js,并且包含 .d.ts
类型提示,推荐在生产环境使用。
因为这些库表示大数的方式是以 16 进制字符串表示的,通常在实践中还需要使用 Buffer.from()
转换成二进制对象,还是有很多不方便,需要写很多辅助函数。不过以后我们就可以使用官方标准库中的 BigInt 了。
目前(2018 年 5 月 1 日)BigInt 提案已经进入 TC39 stage 3,不过还是被 V8 引擎提前实现,本文所有代码示例基于 Chrome Canary 68.0.3415.0,如下图所示。
1 2 3 4 5 6
| typeof 123;
2n ** 53n;
2n ** 53n + 1n;
|
BigInt 表示没有精度和大小限制的整数,为了兼容性考虑,在数字后面添加后缀n
和普通数字类型区分,使用二进制八进制和十六进制也可以表示。
1 2 3 4 5 6 7 8
| 123n;
0b101n;
0o123n;
0xabcn;
|
数字的字符串形式可以类似于 Number()
使用 BigInt()
直接转换为 BigInt,需要注意的是参数检查和 Number() 是一致的,是不能使用 123n
字符串形式的参数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| 123n;
0b101n;
0o123n;
0xabcn;
BigInt("123");
BigInt("0xa");
BigInt("0b1");
BigInt("0o1");
new BigInt();
BigInt(undefined);
BigInt(null);
|
BitInt 除了不能和 number 类型直接运算之外,其它方面和普通的数值运算没有多少区别,除法运算始终返回整数形式。
BigInt 也存在隐式转换,在相等运算符==
、不同类型运算以及强制类型转化函数,都还存在 JS 远古传统。
1 2 3 4 5 6 7 8 9 10 11 12
| 2n == 2;
2n === 2;
0n == "";
0n == 0;
0n == false;
"" + 123n;
|
更多内容可以参考 BigInt 提案