web-dev-qa-db-ja.com

JavaScriptでMath.pow()が(時々)**と等しくないのはなぜですか?

ECMAScript 7の機能a**bMath.pow(a,b)の代替として発見しました( MDNリファレンス )。 その投稿 で議論に出会いましたそれらは明らかに異なる振る舞いをしています。 Chrome 55でテストし、結果が異なることを確認できます。

Math.pow(99,99)3.697296376497263e+197を返します

一方、

99**993.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
113
Thomas Altmann

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のバグのように見えます。それは 報告されている であり、うまくいけばすぐに修正されるでしょう。

122
georg