ECMAScript 2020 的 BigInt 遇到的精度问题及解决方法

阅读时长 4 分钟读完

在 ES2020 中,BigInt 成为了官方的数字类型之一。BigInt 可以表示任意大的整数,而不像 Number 类型那样受到 53 位二进制浮点数精度限制。这种改变为 JavaScript 中数字运算带来了很大的便利,但同时也存在一些问题,本文将针对 BigInt 遇到的精度问题进行分析,并给出解决方法。

问题

假设我们要计算一个非常大的数字的平方,可以使用 BigInt 来进行计算:

代码中,我们使用了 ** 运算符计算了 x 的平方。在这里,我们假设 x 是一个非常大的数字,无法用普通的 Number 类型来表示。因此,我们使用 BigInt 类型来表示 x。 但是在计算 x ** 2n 的时候,我们发现结果并不是我们所期望的。

我们可以通过以下代码来手动计算 123456789123456789 的平方:

-- -------------------- ---- -------
----- - - ---------------------

--- ------ - ---
--- ----- - --

-- ------
--- ---- - - -------- - -- - -- -- ---- -
  ----- ----- - ---------------

  --- --- - ----- - ----- - ------
  ----- - -------------- - ----

  ------ - ---- - --- - -------
-

-- ----
-- ------- -
  ------ - ----- - -------
-

--------------------
-- --- -----------------------------------

通过手动计算可以发现,实际上 123456789123456789 的平方与 BigInt 计算出的结果相同。那为什么在控制台打印出来的结果最后面多了一个 n 呢?

原因

这个问题的原因在于 JavaScript 中 BigInt 类型的表示方法和普通 Number 类型还是有所不同。BigInt 类型的标记方式是在数字后面添加一个 n,例如 1234n 表示一个 BigInt 数字,而普通 Number 类型是不需要使用标记来表示的。

如果我们只是简单地使用 console.log() 方法打印出一个 BigInt 数字,那么它默认会以标准的字符串形式输出。这也就是为什么我们会看到一个多余的 n

在之前的代码中,我们使用了 console.log() 方法打印出了 result 的值。因为 result 是一个 BigInt 值,所以控制台输出的字符串结尾自然会多一个 n

但是该问题不仅仅是只有打印输出的格式,实际上 BigInt 还存在另一个精度问题:当使用 BigInt 进行数字运算时,如果数字长度超过一定界限,会出现精度不准确的情况。

例如,如果我们尝试计算 1000000000000000000000000000000000000n + 1n,我们会得到的结果却是 1000000000000000000000000000000000001 而不是我们所期望的结果。这是由于在计算时,计算机将这个数当作一个普通的 Number 类型处理,而普通的 Number 类型是无法表示这么大的数字的。

解决方法

为了解决使用 BigInt 带来的精度问题,我们需要使用 BigInt 自带的方法来进行运算。BigInt 类型提供了一系列的运算方法,包括加、减、乘、除等操作。这些方法都可以确保计算时不会出现精度问题。

因此,我们需要将以上示例中的 x ** 2n 运算变为 x * x, 即使用 BigInt 提供的乘法运算方法:

在这里,我们将 ** 运算替换成了 * 运算,并使用了 BigInt 的 toString 方法来将结果转换为字符串,以避免 n 的输出问题。

通过这种方式,我们就可以在 JavaScript 中正确地使用 BigInt 进行数字运算了,并且避免了可能会带来精度问题的计算方式。

总结

在使用 BigInt 进行数字运算时,需要注意以下几点:

  • BigInt 类型的标记方式是在数字后面添加一个 n
  • 如果直接将 BigInt 值打印输出,会默认以带有 n 的字符串形式输出;
  • 在使用 BigInt 进行数字运算时,需要使用 BigInt 自带的方法来进行运算,以避免可能会带来精度问题的计算方式。

通过以上的解决方法,我们可以轻松地在 JavaScript 中正确使用 BigInt 进行数字运算,并避免遇到可能会带来的精度问题。

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/6590b934eb4cecbf2d60284c

纠错
反馈