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

时间:2018-11-28 10:44:48

标签: javascript google-chrome v8 bigint spidermonkey

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

  • V8引擎是否缺少这种情况的实现?

我的意思是,如果您尝试9**9**9,它将返回Infinity,这很好。

  • 为什么在前一种情况下V8也不会返回Infinity
  • 为什么它似乎陷入无限循环?

我也在Firefox中尝试过此操作,并且此问题不存在,因为当前SpiderMonkey中没有BigInt实现。

谢谢!

3 个答案:

答案 0 :(得分:9)

如前所述,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

答案 1 :(得分:1)

背景信息:

在JavaScript中,您可以使用n后缀将数字设为bigint(简单大数字)。大数字有不同的计算方式。通常,它们的计算更“昂贵”。它不使用处理器内置方法进行计算。相反,bigints使用软计算。

问题描述:

9n ** 9n表示9 ^ 9(9 * 9 * 9 * 9 * 9 * 9 * 9 * 9 * 9)。它是387420489。即使您自己乘以387420489,它的确是很大的数字。但是** 9n表示您要计算387420489 ^ 9,这确实是一个非常大的数字。对于chrome来说似乎计算时间太长,否则会发生一些未知的问题。

基本上,它必须是一个需要报告的错误。以奇怪的方式冻结浏览器并不是良好的用户体验。

答案 2 :(得分:1)

关于9**9**9返回无穷大的原因的答案是,溢出最大值不会花费很长时间(大约2 ^ 1024)。它甚至可以用**来简化它,就像第一个数字> = 2和第二个数字> 1024,那么它将是Infinity。

使用BigInt,它可以表示很多很多,所以这就是它试图做的。使用BigInt达到“无穷大”需要很长时间(编辑:这实际上是RangeError异常)。找到387420489可以很快完成,但是9n**387420489n的确使BigInts增长了将近4亿倍……这需要一段时间。

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