如果您在 Chrome 的控制台中尝试 9n**9n**9n,Chrome 会中断(类似于无限循环)。为什么会这样?

If you try 9n**9n**9n in Chrome's console, Chrome breaks (it resembles an infinite loop). Why does this happen?

如果您在 Chrome 的控制台中尝试 9n**9n**9n,Chrome 会中断(类似于无限循环)。

我的意思是,如果您尝试 9**9**9,它会 return Infinity,这很好。

我在 Firefox 中也试过了,这个问题不存在,因为目前 SpiderMonkey 中没有 BigInt 实现。

谢谢!

背景资料:

在 JavaScript 中,您可以使用 n 后缀使数字成为 bigint(简单的大数字)。大数有不同的计算方式。通常它们需要 "expensive" 来计算。它不使用处理器的内置方法进行计算。相反,bigints 使用软计算。

问题描述:

9n**9n 表示 9^9 (9*9*9*9*9*9*9*9*9)。它是 387420489。即使你将 387420489 乘以它本身也是一个很大的数字。但是 **9n 意味着你想要计算 387420489^9 这确实是一个非常大的数字。似乎 chrome 计算时间太长或发生了一些未知问题。

基本上这肯定是一个需要报告的错误。以奇怪的方式冻结浏览器不是很好的用户体验。

如前所述,9n9 的 BigInt 表示。

**(幂)运算符从右到左工作,导致结果快速升级:

2n**2n**2n === 2n ** 4n === 16n
3n**3n**3n === 3n ** 27n === 7625597484987n
4n**4n**4n === 4n ** 256n === 13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084096n

在我的系统上,这从 7n**7n**7n 开始变得非常缓慢,需要大约 32 秒才能 计算 打印。结果是695976位,控制台打印前5000位

我还没有进一步尝试,但我想说它只是在咀嚼结果。这可能需要数小时或数天才能计算 打印(或者甚至可能在某个时候发生内存不足的情况)。

更新:

我刚刚在 Chrome 控制台中尝试了 var x = 7n**7n**7n,所以只是将它分配给一个变量,这几乎很快就完成了。事实证明,将 bigint 转换为字符串 是占用时间的;打印 x.toString().length 与打印 x7n**7n**7n.

花费的时间相似

进一步的实验揭示了其他有趣的行为,请参阅这些结果:

// Pure calculation time increases significantly when the exponent grows:
var x = 7n**7n**7n; // ~   1200 ms
var x = 7n**8n**7n; // ~   7000 ms
var x = 7n**7n**8n; // ~  62000 ms
var x = 7n**8n**8n; // ~ 470000 ms

// But it's a different story when the base number is 'simple' in binary terms, e.g. 8n:
var x = 8n**7n**7n; // ~      1 ms
var x = 8n**8n**7n; // ~      1 ms
var x = 8n**7n**8n; // ~      7 ms
var x = 8n**8n**8n; // ~     17 ms

是的,一切都结束了:

var x = 32n**16n**8n;

给出:

VM436:1 Uncaught RangeError: Maximum BigInt size exceeded
at <anonymous>:1:28

Chrome 中的上限似乎是 10 亿位(1e9 位),或大约 125 MB - 参考:https://github.com/tc39/proposal-bigint/issues/174#issuecomment-437471065

为什么 9**9**9 returns Infinity 的答案是因为不需要很长时间就可以溢出最大值(大约 2^1024)。它甚至可以用 ** 快捷方式查看第一个数字 >= 2 和第二个数字 > 1024,那么它将是无穷大。

使用 BigInt,它可以表示大得多的数字,所以这就是它试图做的。使用 BigInt 到达 "Infinity" 需要很长时间(编辑:这实际上是一个 RangeError 异常)。查找 387420489 可以很快完成,但是 9n**387420489n,它将 BigInts 相乘近 4 亿次......这需要一段时间。

BigInt 操作比常规 int 操作慢得多。我希望如果您等待 20-30 分钟,您可能会得到结果(或 RangeError 异常),但可能会更长。