在 ES2020 中,BigInt 成为了官方的数字类型之一。BigInt 可以表示任意大的整数,而不像 Number 类型那样受到 53 位二进制浮点数精度限制。这种改变为 JavaScript 中数字运算带来了很大的便利,但同时也存在一些问题,本文将针对 BigInt 遇到的精度问题进行分析,并给出解决方法。
问题
假设我们要计算一个非常大的数字的平方,可以使用 BigInt 来进行计算:
const x = BigInt("123456789123456789"); const result = x ** 2n; console.log(result); // 输出: 15241578780673678515622620750190521n
代码中,我们使用了 **
运算符计算了 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 提供的乘法运算方法:
const x = BigInt("123456789123456789"); const result = x * x; console.log(result.toString()); // 输出: 15241578780673678515622620750190521
在这里,我们将 **
运算替换成了 *
运算,并使用了 BigInt 的 toString
方法来将结果转换为字符串,以避免 n
的输出问题。
通过这种方式,我们就可以在 JavaScript 中正确地使用 BigInt 进行数字运算了,并且避免了可能会带来精度问题的计算方式。
总结
在使用 BigInt 进行数字运算时,需要注意以下几点:
- BigInt 类型的标记方式是在数字后面添加一个
n
; - 如果直接将 BigInt 值打印输出,会默认以带有
n
的字符串形式输出; - 在使用 BigInt 进行数字运算时,需要使用 BigInt 自带的方法来进行运算,以避免可能会带来精度问题的计算方式。
通过以上的解决方法,我们可以轻松地在 JavaScript 中正确使用 BigInt 进行数字运算,并避免遇到可能会带来的精度问题。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/6590b934eb4cecbf2d60284c