ホームページ >Java >&#&チュートリアル >なぜ二重の精度を失うのか、そしてjavaでそれを避ける方法

なぜ二重の精度を失うのか、そしてjavaでそれを避ける方法

Patricia Arquette
Patricia Arquetteオリジナル
2025-01-27 18:09:10940ブラウズ

Why double Loses Precision and How to Avoid It in Java

Javaでフローティングポイント数を使用する場合、2倍が事故または不正確な結果を生成することがあることに気付くかもしれません。この動作は、特に金融アプリケーションや高度の高度シナリオでエラーを引き起こす可能性があります。

この記事では、この問題の根本原因を調査し、それを回避する方法を説明し、実行可能な例を提供し、更新されたJavaバージョンがより良い代替ソリューションを提供するかどうかを議論します。

なぜ二重の精度が失われるのですか?

1。IEEE754フローティングポイント番号標準

Javaの二重データ型は、IEEE 754 Floating -Point番号計算標準に従います。次の方法を使用して、バイナリ形式で数値を表します。

シンボルの場合、

1桁

11桁
    インデックスに使用、
  • 52-スコア(テール番号)に使用される
  • このバイナリステートメントは、制限を導入しました:
  • 限られた精度:ダブルは最大15〜17ビットの小数を正確に表すことができます。
  • 取り込み誤差
:多くの小数スコア(例えば、0.1)をバイナリ番号として正確に表現することはできません。

たとえば、バイナリ:
  • 0.1は無制限のサイクル小数になり、ストレージのために遮断され、それによって軽度の不正確さが導入されます。
  • 2。算術操作における累積誤差 ダブルに伴う操作は、エラーが蓄積する可能性があります:

追加/削減方法が繰り返されると、エントリエラーが増幅されます。

    乗算/除去は、切り捨てにより精度を失う可能性があります。
この動作は、Javaユニークではなく、浮遊点数に固有のものです。

実行可能な例:double

によって引き起こされる精度の精度
    これはデモの問題の例です:
  • output:

result 0.30000000000000004は、バイナリ表現によって引き起こされる腐敗エラーを強調しています。違いがわずかに取るに足らない場合でも、キーシステムの大きな問題につながる可能性があります。

精度の損失を回避する方法

1。正確な計算にはbigdecimalを使用します
<code class="language-java">public class DoublePrecisionLoss {
    public static void main(String[] args) {
        double num1 = 0.1;
        double num2 = 0.2;
        double sum = num1 + num2;

        System.out.println("预期和:0.3");
        System.out.println("实际和:" + sum);

        // 比较
        if (sum == 0.3) {
            System.out.println("和等于0.3");
        } else {
            System.out.println("和不等于0.3");
        }
    }
}</code>

JavaのBigdecimalクラスは、任意の精度算術を提供し、高い精度(金融コンピューティングなど)を必要とする理想的な選択肢となっています。 BigDecimalを使用する例:

<code>预期和:0.3
实际和:0.30000000000000004
和不等于0.3</code>

output:


BigDecimalを使用することにより、精度の問題が排除され、正しい結果が比較されました。

2。epsilon値を使用して

を比較します

精度の損失に対処する別の方法は、浮動点の数を許容範囲(Epsilon)と比較することです。この方法では、正確な平等性に依存するのではなく、数値が「十分に近い」かどうかをチェックします。

Epsilon比較の使用例:

<code class="language-java">import java.math.BigDecimal;

public class BigDecimalExample {
    public static void main(String[] args) {
        BigDecimal num1 = new BigDecimal("0.1");
        BigDecimal num2 = new BigDecimal("0.2");
        BigDecimal sum = num1.add(num2);

        System.out.println("预期和:0.3");
        System.out.println("实际和:" + sum);

        // 比较
        if (sum.compareTo(new BigDecimal("0.3")) == 0) {
            System.out.println("和等于0.3");
        } else {
            System.out.println("和不等于0.3");
        }
    }
}</code>

output:

<code class="language-java">public class DoublePrecisionLoss {
    public static void main(String[] args) {
        double num1 = 0.1;
        double num2 = 0.2;
        double sum = num1 + num2;

        System.out.println("预期和:0.3");
        System.out.println("实际和:" + sum);

        // 比较
        if (sum == 0.3) {
            System.out.println("和等于0.3");
        } else {
            System.out.println("和不等于0.3");
        }
    }
}</code>

なぜEpsilonを使用して比較するのですか?

  • 柔軟性:組み込み誤差によって引き起こされる小さな違いを可能にします。
  • シンプル
  • :この方法では、外部ライブラリを必要とせず、効率が高くなります。
Apache Commons Mathを使用して、精度を向上させますApache Commons Mathは、複雑な数学的コンピューティング用に設計されたライブラリです。 Bigdecimalのように任意の精度算術を提供しませんが、数値操作を簡素化し、場合によっては浮動ポイントエラーを最小限に抑える実用的な手順を提供します。

例:precision.equalsを使用して

を比較します

output:

<code>预期和:0.3
实际和:0.30000000000000004
和不等于0.3</code>

なぜApache Commons Mathを使用するのですか?

<code class="language-java">import java.math.BigDecimal;

public class BigDecimalExample {
    public static void main(String[] args) {
        BigDecimal num1 = new BigDecimal("0.1");
        BigDecimal num2 = new BigDecimal("0.2");
        BigDecimal sum = num1.add(num2);

        System.out.println("预期和:0.3");
        System.out.println("实际和:" + sum);

        // 比较
        if (sum.compareTo(new BigDecimal("0.3")) == 0) {
            System.out.println("和等于0.3");
        } else {
            System.out.println("和不等于0.3");
        }
    }
}</code>
単純化された比較

:precision.equalsは、指定された許容範囲を使用して、組み込みエラーを簡単に処理するために、指定された許容範囲と比較できるようにします。

    LightWeight
  • :ライブラリは、BigDecimalの費用を増やすことなく数値計算に焦点を当てたツールを提供します。
  • 要約 制限を理解する
  • :ダブル自体に欠陥はありませんが、バイナリの浮動小数点表現のため、高精度のタスクには適していません。

bigdecimal

:bigdecimalは正確性を確保できますが、財務または重要な計算のパフォーマンスに影響を与える可能性があります。

    ライブラリの使用
  • :Apache Commons Mathは、フローティングポイントの比較を効果的に処理できるPrecision.equalsなどの実用的なプログラムを提供します。
  • ダブルとその代替案を理解することにより、より堅牢でより正確なJavaアプリケーションを書くことができます。
  • ダブルの正確さとこれらの問題を解決する方法に遭遇した場合は、コメントで教えてください! ?

以上がなぜ二重の精度を失うのか、そしてjavaでそれを避ける方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。