为啥 JavaScript 中的 Math.pow()(有时)不等于 **?
Posted
技术标签:
【中文标题】为啥 JavaScript 中的 Math.pow()(有时)不等于 **?【英文标题】:Why is Math.pow() (sometimes) not equal to ** in JavaScript?为什么 JavaScript 中的 Math.pow()(有时)不等于 **? 【发布时间】:2017-05-31 10:58:02 【问题描述】:我刚刚发现了 ECMAScript 7 功能 a**b
作为 Math.pow(a,b)
(MDN Reference) 的替代品,并在 that post 中进行了讨论,其中它们的行为显然不同。我已经在 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;
调用diff(99)
返回0
。
为什么会这样?
正如xszaboj 所指出的,这可以缩小到这个问题:
var x = 99;
x**x - 99**99; // Returns -5.311379928167671e+182
【问题讨论】:
听起来好像有人重写了他们使用的算法,发现了一个floating point error。数字很难...... @krillgar 听起来很合理,但为什么函数中没有发生同样的错误呢? @AndersonPimentel MDN 链接指向compatibility table。 这两者之间的区别是:var x = 99; x * * x ;和 99 * * 99。或 function diff(x) return 99 * * 99 - (x * * x); ;差异(99)。对不起,评论过滤了两颗星:( @xszaboj 将代码放入反引号`likethis`
以使其可读并避免粗体/斜体问题
【参考方案1】:
99**99
是evaluated at compile time(“常量折叠”),编译器的pow
routine 与runtime one 不同。在运行时评估**
时,结果与Math.pow
相同——难怪**
实际上是compiled 到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
其实
99 99 SUP> = 369729637649726772657187905628805440595668764281741102430259972423552570455277523421410650010128232727940978889548326540119429996769494359451621570193644014418071060667659301384999779999159200499899 SUP>
所以第一个结果是一个更好的近似值,但常量表达式和动态表达式之间不应该出现这种差异。
这种行为看起来像 V8 中的一个错误。它has been reported 并有望很快得到修复。
【讨论】:
所以它基本上是 JS 试图通过预先计算99**99
来提高性能?这可以被认为是一个错误,因为Math.pow
为数字和变量创建了相同的输出,而**
没有?
@ThomasAltmann: Math.row
始终是运行时的,const 折叠只能对操作符进行。是的,这绝对是一个错误。
一个错误has been logged,从这里的 OP 看来。
我正在使用 MS Edge,所有 3 个结果都相同:分别为 3.697296376497263e+197
、3.697296376497263e+197
和 3.697296376497263e+197
。这绝对是一个 Chrome 错误。
@ThomasAltmann 如果常量折叠产生的 worse 值比运行时 impl 值,那么它就是一个错误。如果它产生比运行时更好 的值,那么它可能会或可能不会被视为错误。在这种情况下,它会更好——正确的值是“... 26772...”,常量折叠产生“...268”(正确舍入),运行时产生“...263”(关闭 4+单位在最后)。以上是关于为啥 JavaScript 中的 Math.pow()(有时)不等于 **?的主要内容,如果未能解决你的问题,请参考以下文章