为什么Math.pow()(有时)在JavaScript中不等于**?

Tho*_*ann 114 javascript google-chrome v8 ecmascript-7

我刚刚发现ECMAScript 7功能a**b作为Math.pow(a,b)(MDN参考)的替代方案,并且在该帖子中遇到了一个讨论,其中他们显然表现不同.我在Chrome 55中测试了它,可以确认结果有所不同.

Math.pow(99,99) 回报 3.697296376497263e+197

99**99 回报 3.697296376497268e+197

因此记录差异会Math.pow(99,99) - 99**99导致-5.311379928167671e+182.

到目前为止可以说,它只是另一种实现,但将它包装在一个函数中的行为又有所不同:

function diff(x) {
  return Math.pow(x,x) - x**x;
}
Run Code Online (Sandbox Code Playgroud)

调用diff(99)返回0.

为什么会这样?

正如xszaboj指出的那样,这可以缩小到这个问题:

var x = 99;
x**x - 99**99; // Returns -5.311379928167671e+182
Run Code Online (Sandbox Code Playgroud)

geo*_*org 122

99**99在编译时评价("常量折叠"),以及编译器的pow程序是从不同的运行时一个.**在运行时进行评估时,结果是相同的Math.pow- 难怪因为**实际编译Math.pow调用:

console.log(99**99);           // 3.697296376497268e+197
a = 99, b = 99;
console.log(a**b);             // 3.697296376497263e+197
console.log(Math.pow(99, 99)); // 3.697296376497263e+197
Run Code Online (Sandbox Code Playgroud)

其实

99 99 = 369729637649726772657187905628805440595668764281741102430259972423552570455277522521410650010128232727940978889548326540119429996769494359451621570193644014418071060667659301384999779999159200499899

所以第一个结果是更好的近似,仍然不应该发生恒定和动态表达之间的这种差异.

此行为看起来像V8中的错误.据报道,很快就会得到解决.

  • 所以基本上JS试图通过事先计算"99**99"来提高性能?这可能被认为是一个错误,因为`Math.pow`为数字和变量创建了相同的输出,而`**`没有? (18认同)
  • 一个错误[已被记录](https://bugs.chromium.org/p/v8/issues/detail?id=5848),由OP在这里的事情看起来. (11认同)
  • 我正在使用MS Edge,所有3个结果都是相同的:`3.697296376497263e + 197`,`3.697296376497263e + 197`和`3.697296376497263e + 197`.这绝对是一个Chrome bug. (5认同)
  • @ThomasAltmann如果常量折叠产生比运行时impl更差的*值,那么它就是一个bug.如果它产生比运行时更好的*值,那么它可能会或可能不会被视为错误.在这种情况下,它更好 - 正确的值是"... 26772 ...",常量折叠产生"... 268"(正确舍入),运行时产生"... 263"(关闭4+最后一个单位). (4认同)
  • @ThomasAltmann:`Math.row`总是运行时,const折叠只能为运算符完成.是的,这绝对是个错误. (3认同)