2

重複の可能性:
Java で Doubles を使用して精度を保持する

わかりましたので、次のコードのチャンクを取得しました。

int rotation = e.getWheelRotation();
if(rotation < 0)
    zoom(zoom + rotation * -.05); 
else if(zoom - .05 > 0)
    zoom(zoom - rotation * .05);

System.out.println(zoom);

現在、ズーム変数は double 型で、最初は 1 に設定されています。したがって、結果は 1 - .05 = .95; のようになると予想されます。.95 - .05 = .9; .9 - .05 = .85; など。以下に示すように結果を印刷すると、そうではないように見えます。

  • 0.95
  • 0.8999999999999999
  • 0.8499999999999999
  • 0.7999999999999998
  • 0.7499999999999998
  • 0.6999999999999997

誰かが明確に説明できることを願っています。インターネットを検索したところ、フロートをバイナリで保存する際の制限と関係があると読みましたが、まだよくわかりません。私の問題の解決策は驚くほど重要ではありませんが、この種の動作を理解したいと思います。

4

4 に答える 4

3

Java はIEEE-754浮動小数点数を使用します。それらは完全に正確ではありません。有名な例は次のとおりです。

System.out.println(0.1d + 0.2d);

...出力します0.30000000000000004

あなたが見ているのは、その不正確さの兆候にすぎません。doubleではなくを使用することで、精度を向上させることができますfloat

財務計算を扱っている場合は、 または を好むかもしれBigDecimalませfloatdouble

于 2012-06-11T09:43:19.413 に答える
3

floatまたdouble、小数部分が 2 の累乗で表されるため、精度が制限されます。たとえば、1/2 + 1/4 + 1/8 などです。

このため、浮動小数点を扱う場合は常に、適切な丸めを使用する必要があります。そうしないと、小さなエラーが発生する可能性があります。

例えば

System.out.printf("%.2f%n", zoom);

ラウンド エラーを最小限に抑えるには、代わりに回転数を数​​えて、このint値を 20.0 で割ります。この方法では丸め誤差が発生せず、マジック ナンバーが少なくて高速になります。

于 2012-06-11T09:55:17.727 に答える
0

floatdouble精度の問題があります。BigDecimal Classをご覧になることをお勧めします。それは精度の問題を処理するはずです。

于 2012-06-11T09:42:55.517 に答える
0

10 進数 (および整数も) は可能な値の数が無限にある可能性があるため、標準形式を使用して正確にビットにマップすることは不可能です。コンピュータは、数値が想定できる範囲を制限することで、この問題を回避します。

たとえば、 Java の は、2^31 - 1intより大きい値を表すことはできません。Integer.MAX_VALUE

10 進数の場合、カンマの後の数字にも問題があり、これも無限になる可能性があります。これは、すべての小数値を許可するのではなく、2 のべき乗に基づいて (賢明に選択された) 可能性の数を制限することで解決されます。これは自動的に行われますが、多くの場合、心配する必要はありません。結果の 0.899999 を 0.9 と解釈できます。明示的な精度が必要な場合は、他の制限がある可能性がある他のデータ型に頼る必要があります。

于 2012-06-11T10:00:38.410 に答える