使用JavaScript的BigInt数据类型

作者 : IT 大叔 本文共2371个字,预计阅读时间需要6分钟 发布时间: 2020-10-15

正如所有Web开发人员所知道的那样,JavaScript有点奇怪,它在幕后的编译和功能方式上有各种各样有趣的怪癖。

该语言最有趣的方面之一是它直到最近才仅使用一种数据类型来存储数字:一个Number对象。这个对象之间不指定整数浮动的方式很多其他语言做,而是将它们存储在所有引擎盖下同样的双精度64位浮点格式

但是,从JavaScript的ECMA规范的最新版本开始,现在存在另一种用于存储和使用数字的方法:BigInt对象。


我们为什么需要它?

JavaScript存储数字的方式的问题是,当存储非常大的整数时会发生溢出,从而导致自动舍入和精度问题。

JavaScript中的Number对象只能安全地存储以下之间的整数:

-9007199254740991(-(2 53 -1))

和:

9007199254740991(2 53 -1)

可以通过console.logging记录以下内容来查看溢出不准确的影响:

console.log(9999999999999999);
// => 10000000000000000

要么:

// note the final digits
console.log(9007199254740992 === 9007199254740993);
// => true

在大多数小规模编程或Web开发工作流程中,这似乎并不是什么大问题。但是,随着JavaScript作为一种后端语言变得越来越流行,并且随着使用该语言编写的数据库和逻辑越来越多,最大安全整数的问题已变得足够普遍,以使该语言的国际标准的维护者可以从本地解决该问题。


BigInt来了!

传统上,JavaScript开发人员已经找到解决最大整数大小问题的方法,例如将大整数插值到字符串中并以这种方式存储它们,或者使用其他开发人员构建的开源库。

但是,由于引入了BigInt,该问题已在语言本身内得到正式解决。

要创建BigInt对象,只需在不安全整数的末尾附加“ n”,或将整数包装在“ BigInt()”构造函数中,如下所示:

let largeNum1 = 9007199254740995n
// or
let largeNum2 = BigInt("9007199254740995")
// note that the integer is being parsed as a string,
// otherwise rounding may occur

大功告成!

可以使用以下简单运算符对BigInt对象进行算术运算:+,-,*,/,**和%

值得注意的是,使用JavaScript中的Math对象的内置方法不适用于BigInts,并且在BigInt和常规Number之间执行的任何算术运算都将不起作用-Number必须首先也被强制转换为BigInt。

有关BigInt对象的更详细信息,请参见MDN WebDocs页面:BigInt-JavaScript | MDN


您能给我一个BigInt用例的实际例子吗?

绝对!

假设您要解决一个涉及“链表”的问题,在该问题中,您希望提取两个链表的值,将它们连接成整数,将它们加在一起,然后返回总和。

您的解决方案可能如下所示:

const addTwoNumbers = function(l1, l2) {

    // Helper method to concatenate list values
    function getNum(node) {
        let string = "";
        while (node) {
            string += node.val;
            node = node.next;
        }
        return string;
    }

    let l1Num = getNum(l1);
    let l2Num = getNum(l2);

    let sum = (parseInt(l1Num) + parseInt(l2Num));

    return sum;
};

在以下输入情况下(假设数组中的每个元素都是“链表”的节点值)

[7,2,4,3]
[5,6,4,2]

您将获得7,243 + 5,642 = 12,885的期望值。大!

但是,使用类似以下的输入情况:

[2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,9]
[5,6,4,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,9,9,9,9]

那些数字很大!

如果我们尝试像以前一样简单地使用parseInt()将那些连接的字符串解析为整数,那么我们的准确性将完全消失,解决方案将无法在生产中使用。

在这种情况下,BigInt是完美的工具。我们可以稍微改变一下解决方案,以使用BigInt解析语法代替parseInt(),如下所示:

const addTwoNumbers = function(l1, l2) {

    // Helper method to concatenate list values
    function getNum(node) {
        let string = "";
        while (node) {
            string += node.val;
            node = node.next;
        }
        return string;
    }

    let l1Num = getNum(l1);
    let l2Num = getNum(l2);

    // note the difference \/ !
    let sum = (BigInt(l1Num) + BigInt(l2Num));

    return sum;
};

现在,我们将获得准确计算的总数!

如果值小于最大安全整数大小,则可以实施一些额外的逻辑将值强制转换回Number对象,以便该解决方案适用于所有数据大小。

免责声明:
1. 本站资源转自互联网,源码资源分享仅供交流学习,下载后切勿用于商业用途,否则开发者追究责任与本站无关!
2. 本站使用「署名 4.0 国际」创作协议,可自由转载、引用,但需署名原版权作者且注明文章出处
3. 未登录无法下载,登录使用金币下载所有资源。
IT小站 » 使用JavaScript的BigInt数据类型

常见问题FAQ

没有金币/金币不足 怎么办?
本站已开通每日签到送金币,每日签到赠送五枚金币,金币可累积。
所有资源普通会员都能下载吗?
本站所有资源普通会员都可以下载,需要消耗金币下载的白金会员资源,通过每日签到,即可获取免费金币,金币可累积使用。

发表评论