2

この JavaScript は、IE のバグを示しており、現在私を悩ませています。

var y = 6044629098073143; // this exact integer easily fits into an IEEE double
document.write(y + " " + Math.round(y)+"<br><br>");

IE 8 (および Opera 12.02) の出力はMath.round、1 だけずれていることを示しています。

6044629098073143 6044629098073144

Firefox、Chrome、Safari での出力は正しいです。

IE と Opera でいったい何が起こっているのでしょうか。

4

2 に答える 2

3

RobGのコメントを確認しました。2^52(4503599627370496)未満のすべての整数は、すべてのブラウザーで正しく丸められているように見えます。この値よりも大きい整数は、IE / OperaでMath.roundを使用して偶数に切り上げられます(他のブラウザーは正しく丸められます)。

RobGが述べたように、IEとOperaはMath.round(x)をMath.floor(x + 0.5)として実装する可能性があります。これは、値> 2 ^ 52に0.5を加算すると不正確な結果になるため、これらの結果につながります。round()のよりスマートな実装では、FPUのネイティブ丸めサポートを使用します(IEおよびOpera開発者、注意して修正してください!)

それまでの間、この回避策は機能するはずです。

// workaround for IE and Opera's brain-dead Math.round() implementation
if (y < 4503599627370496) // 2^52
{
  y = Math.round(y);
}
// else 'y' is already an integer
于 2012-10-11T19:07:42.510 に答える
1

上記のコメントでRobGが述べているように、Opera IEでは、動作が保証されている最大の整数値は4503599627370496(2 ^ 52)です。

興味深いことに、これは一部の浮動小数点値にも当てはまります。それより大きい数の場合、浮動小数点数も精度を失います。ここ
に 表示されているように、doubleには52ビットの精度の仮数があります。これは、4503599627370496より大きいすべての数値について、仮数が常に表示された数値の最上位ビット(MSB)に揃えられるため、最後の桁がトリミングされることを意味します。

Operaのコンソールに入力:

//This works
>>> 4503599627370494.5 //Consumes 53 bits
4503599627370494.5
>>> 4503599627370495.5 //Consumes 53 bits
4503599627370495.5
//This works no more, the last bit is now needed
>>> 4503599627370496.5 //Consumes 54 bits
4503599627370496

そして、この精度の低下は、これらのブラウザが数値の正確な表現を持たない理由を説明しています。最後のビットは単純に丸められます。Machine_epsilonも参照してください。
ただし、この観察結果から結論できるのは、質問に示されている整数は間違いなくdoubleに変換されるということです。

于 2012-10-11T06:50:06.273 に答える