5

1.265 に 10000 を掛けると、Javascript を使用すると 126499.99999999999 が得られます。

これはなぜですか?

4

10 に答える 10

25

浮動小数点数は、常に小数を正しく処理できるわけではありません。チェックアウト

于 2009-06-08T08:19:48.147 に答える
11

コンピューター内のすべての情報は2進数であり、基数が異なると分数の展開が異なることに注意してください。

たとえば、基数10の1/3 = .33333333333333333333333333であるのに対し、基数3の1/3は.1に等しく、基数2の1/3は.0101010101010101に等しくなります。

さまざまなベースがどのように機能するかを完全に理解していない場合は、次の例を参照してください。

基数4の番号301.12。3 * 4 ^ 2 + 0 * 4 ^ 1 + 1 * 4 ^ 0 + 1 * 4 ^ -1 + 2 * 4 ^ -2 = 3 * 4 ^ 2 + 1+ 1 * 4^-1に等しくなります+ 2 * 4 ^ -2 = 49.375(10進数)。

現在、浮動小数点の精度に関する問題は、仮数の限られたビット数に起因しています。浮動小数点数には、符号ビット、指数、仮数の3つの部分があり、ほとんどの場合、javascriptは32ビットまたは64ビットのIEEE754浮動小数点標準を使用します。より簡単な計算では32ビットを使用するため、浮動小数点の1.265は次のようになります。

0の符号ビット(正の場合は0、負の場合は1)指数0(127のオフセットを使用すると、指数+オフセットになるため、符号なしバイナリでは127になります)01111111(最終的に1.265の符号、つまり浮動小数点が得られます標準では非表示の1表現を使用するため、1.265のバイナリ再設定は1.01000011110101110000101であり、1:)01000011110101110000101は無視されます。

したがって、1.625の最終的なIEEE 754シングル(32ビット)表現は次のようになります。

Sign Bit(+)      Exponent (0)       Mantissa (1.625)
0                 01111111          01000011110101110000101

今1000は次のようになります:

符号ビット(+)指数(9)仮数(1000)0 10001000 11110100000000000000000

次に、これら2つの数値を乗算する必要があります。浮動小数点の乗算は、両方の仮数に非表示の1を再度加算し、2つの仮数を乗算し、2つの指数からオフセットを減算してから、2つの指数を加算することで構成されます。この後、仮数を再度正規化する必要があります。

最初の1.01000011110101110000101*1.11110100000000000000000 = 10.0111100001111111111111111000100000000000000000(この乗算は苦痛です)

これで、明らかに指数が9 +指数が0になるため、指数として10001000を維持し、符号ビットが残るため、残っているのは正規化だけです。

仮数は1.000000の形式である必要があるため、仮数を1.00111100001111111111111111000100000000000000000に正規化したので、仮数を1回右にシフトする必要があります。これは、指数を増分して10001001にする必要があることも意味します。23ビットに切り捨てる必要があるため、1.00111100001111111111111が残ります(最終的な表現では非表示になるため、1は含まれません)。したがって、最終的な答えは次のようになります。

Sign Bit (+)   Exponent(10)   Mantissa
0              10001001       00111100001111111111111

最後に、この答えを小数に戻すと、(+)2 ^ 10 *(1+ 2 ^ -3 + 2 ^ -4 + 2 ^ -5 + 2 ^ -6 + 2 ^ -11 + 2 ^ -12 + 2 ^ -13 + 2 ^ -14 + 2 ^ -15 + 2 ^ -16 + 2 ^ -17 + 2 ^ -18 + 2 ^ -19 + 2 ^ -20 + 2 ^ -21 + 2 ^ -22 + 2 ^ -23)=1264.99987792

1000を10000ではなく1.265で乗算し、doubleではなく単精度浮動小数点を使用して問題を単純化した一方で、概念は同じままです。浮動小数点表現には、任意の数値を表すための仮数のビットが非常に多いため、精度の低下を使用します。

お役に立てれば。

于 2009-06-12T19:32:13.927 に答える
5

これは、浮動小数点表現エラーの結果です。有限の 10 進数表現を持つすべての数値が、有限の 2 進浮動小数点表現を持つわけではありません。

于 2009-06-08T08:19:52.080 に答える
4

一方、126500 は 126499.99999999 に等しい.... :)

1 が 0.99999999 に等しいのと同じように....

1 = 3 * 1/3 = 3 * 0.333333... = 0.99999999....

于 2009-06-08T08:22:45.130 に答える
4

この記事を読んでください。本質的に、コンピューターと浮動小数点数は完全には一致しません。

于 2009-06-08T08:19:53.250 に答える
2

純粋に浮動小数点表現の不正確さによるものです。

Math.roundを使用してみることができます:

var x = Math.round(1.265 * 10000);
于 2009-06-08T08:21:03.777 に答える
1

これらの小さなエラーは通常、言語で使用される浮動小数点の精度が原因で発生します。浮動小数点の精度の問題について詳しくは、このウィキペディアのページを参照してください。

于 2009-06-08T08:21:46.083 に答える
1

おそらくあまりきれいではありませんが、これはあなたの問題を克服する方法です:

var correct = parseFloat((1.265*10000).toFixed(3));

// Here's a breakdown of the line of code:
var result = (1.265*10000);
var rounded = result.toFixed(3); // Gives a string representation with three decimals
var correct = parseFloat(rounded); // Convert string into a float 
                                   // (doesn't show decimals)
于 2009-06-08T08:30:27.487 に答える
1

解決策が必要な場合は、float または double の使用をやめ、BigDecimal の使用を開始してください。BigDecimal の実装を確認してくださいstz-ida.de/html/oss/js_bigdecimal.html.en

于 2009-06-12T19:46:08.340 に答える
0

MS JScript エンジンへの追加でも: WScript.Echo(1083.6-1023.6) は 59.9999999 を返します

于 2009-06-08T08:27:59.487 に答える