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

我刚刚发现 ECMAScript 7 功能是 (MDN Reference) 的替代方案,并在该帖子中遇到了一个讨论,其中它们的行为显然不同。我已经在Chrome 55中对其进行了测试,可以确认结果不同。a**bMath.pow(a,b)

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;
}

调用返回 。diff(99)0

为什么会发生这种情况?

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

var x = 99;
x**x - 99**99; // Returns -5.311379928167671e+182

答案 1

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

实际上

9999=369729637649726772657187905628805440595668764281741102430259972423552570455277523421410650010128232727940978889548326540119429996769494359451621570193644014418071060667659301384999779999159200499899

因此,第一个结果是更好的近似值,因此不应发生常量表达式和动态表达式之间的这种差异。

此行为看起来像 V8 中的一个错误。它已被报道,并希望很快得到解决。


答案 2