浮動小数点演算中に精度が失われるリスクがあるのはなぜですか? 浮動小数点演算の精度が失われる問題を解決するにはどうすればよいですか?

浮動小数点演算中に精度が失われるリスクがあるのはなぜですか?

浮動小数点演算の精度の損失に関するコードのデモ:

float a = 2.0f - 1.9f;
float b = 1.8f - 1.7f;
System.out.println(a);// 0.100000024
System.out.println(b);// 0.099999905
System.out.println(a == b);// false

なぜこの問題が起こるのでしょうか?

これは、コンピュータが浮動小数点数を格納するメカニズムと大きく関係しています。コンピューターは 2 進数であり、コンピューターが数値を表すときの幅は制限されており、小数の無限ループはコンピューターに保存するときにのみ切り捨てられるため、小数の精度は失われます。これは、浮動小数点数を 2 進数で正確に表現できない理由も説明します。

たとえば、10 進数の 0.2 は 2 進数の 10 進数に正確に変換できません。

// 0.2 转换为二进制数的过程为,不断乘以 2,直到不存在小数为止,
// 在这个计算过程中,得到的整数部分从上到下排列就是二进制的结果。
0.2 * 2 = 0.4 -> 0
0.4 * 2 = 0.8 -> 0
0.8 * 2 = 1.6 -> 1
0.6 * 2 = 1.2 -> 1
0.2 * 2 = 0.4 -> 0(发生循环)
...

浮動小数点数の詳細については、「コンピュータ システムの基礎 (4) 浮動小数点数」の記事を読むことをお勧めします。

浮動小数点演算の精度が失われる問題を解決するにはどうすればよいですか?

BigDecimal浮動小数点数の演算は、精度を損なうことなく実現できます。通常、浮動小数点数の正確な計算結果を必要とするほとんどのビジネス シナリオ (お金が関係するシナリオなど) は、BigDecimalを通じて実行されます。

BigDecimal a = new BigDecimal("1.0");
BigDecimal b = new BigDecimal("0.9");
BigDecimal c = new BigDecimal("0.8");

BigDecimal x = a.subtract(b);
BigDecimal y = b.subtract(c);

System.out.println(x); /* 0.1 */
System.out.println(y); /* 0.1 */
System.out.println(Objects.equals(x, y)); /* true */

の詳細についてはBigDecimal、私が書いた記事「BigDecimal の詳細な説明 」を参照してください。

おすすめ

転載: blog.csdn.net/qq_34337272/article/details/130035600