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


118

MDNリファレンス)のa**b代替としてECMAScript 7機能を発見しました。その投稿で、動作が明らかに異なるという議論に遭遇しました。Chrome 55でテストしましたが、結果が異なることが確認できました。Math.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

7
誰かが使用したアルゴリズムを書き直したようですが、浮動小数点エラーが見つかりました。数字は難しい...
krillgar

4
@krillgarは妥当に聞こえますが、関数で同じエラーが発生しないのはなぜですか?
Thomas Altmann、2017年

3
@AndersonPimentel MDNリンクは互換性テーブルを指します
アルバロ・ゴンサレス

7
この2つの違いは次のとおりです。varx = 99; x * * x; および99 * *99。または関数diff(x){return 99 * * 99-(x * * x); }; diff(99)。間隔を空けて申し訳ありませんが、コメントは2つの星をフィルター処理します:(
xszaboj 2017年

1
@xszabojはコードをバッククォート`likethis`に入れて読みやすくし、太字/斜体の問題も回避しています
phuclv

回答:


126

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

実は

99 99 = 369729637649726772657187905628805440595668764281741102430259972423552570455277523421410650010128232727940978889548326540119429996769494359451621570193644014418071060667659301384999779999159200499899

したがって、最初の結果はより良い近似ですが、それでも定数式と動的式の間でこのような不一致は発生しません。

この動作はV8のバグのようです。報告さており、まもなく修正される予定です。


19
基本的にJSは99**99事前にコンピューティングでパフォーマンスを改善しようとしているのですか?これはバグと考えることができますか?Math.pow数値と変数に対して同じ出力を作成しますが、**しないのですか?
Thomas Altmann 2017年

3
@ThomasAltmann:Math.row常に実行時であり、constフォールディングは演算子に対してのみ実行できます。はい、それは間違いなくバグです。
georg

11
ここのOPの見た目により、バグが記録されています
James Thorpe

5
私は、MSのエッジを使用していて、すべての3つの結果は同じです:3.697296376497263e+1973.697296376497263e+197、および3.697296376497263e+197それぞれ。間違いなくChromeのバグです。
Nolonar 2017年

4
@ThomasAltmann定数の折りたたみがランタイムの実装よりも悪い値を生成する場合、それはバグです。ランタイムよりも優れた値を生成する場合は、バグと見なされる場合と見なされない場合があります。この場合、より良い—正しい値は "... 26772 ..."であり、定数の折りたたみは "... 268"(正しく丸められます)を生成し、ランタイムは "... 263"(4+オフ)を生成します最後のユニット)。
2017年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.