Heim > Java > javaLernprogramm > Warum doppelt doppelt Präzision verliert und wie man es in Java vermeidet

Warum doppelt doppelt Präzision verliert und wie man es in Java vermeidet

Patricia Arquette
Freigeben: 2025-01-27 18:09:10
Original
961 Leute haben es durchsucht

Why double Loses Precision and How to Avoid It in Java

Wenn Sie in Java mit Gleitkommazahlen arbeiten, stellen Sie möglicherweise fest, dass „Double“ manchmal zu unerwarteten oder ungenauen Ergebnissen führt. Dieses Verhalten kann zu Fehlern führen, insbesondere bei Finanzanwendungen oder Szenarien, die eine hohe Genauigkeit erfordern.

In diesem Artikel werden wir uns mit der Grundursache dieses Problems befassen, erklären, wie man es vermeidet, ein funktionierendes Beispiel bereitstellen und untersuchen, ob neuere Java-Versionen bessere Alternativen bieten.

Warum verliert Double an Präzision?

1. IEEE 754 Gleitkomma-Standard

Der Double-Datentyp in Java folgt dem Gleitkommazahl-Operationsstandard IEEE 754. Es stellt Zahlen im Binärformat dar mit:

  • 1 Bit wird für Symbole verwendet,
  • 11 Bits für Exponent,
  • 52 Bits werden für Brüche (Mantisse) verwendet.

Diese binäre Darstellung führt zu Einschränkungen:

  • Eingeschränkte Genauigkeit: double kann nur bis zu 15–17 Dezimalstellen genau darstellen.
  • Rundungsfehler: Viele Dezimalbrüche (z. B. 0,1) können nicht exakt als Binärzahlen dargestellt werden, was zu Rundungsfehlern führt.

Zum Beispiel im Binärformat:

  • 0,1 wird zu einer unendlich wiederkehrenden Dezimalzahl, die zur Speicherung gekürzt wird, wodurch leichte Ungenauigkeiten entstehen.

2. Kumulativer Fehler bei arithmetischen Operationen

Vorgänge mit Doppelvorgängen können zu Fehlern führen:

  • Wiederholte Additionen/Subtraktionen verstärken Rundungsfehler.
  • Multiplikation/Division kann aufgrund der Kürzung an Präzision verlieren.

Dieses Verhalten ist der Gleitkomma-Arithmetik eigen und nicht nur in Java zu finden.


Praktisches Beispiel: Präzisionsverlust durch die Verwendung von double

Hier ist ein Beispiel, das das Problem verdeutlicht:

<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>
Nach dem Login kopieren
Nach dem Login kopieren

Ausgabe:

<code>预期和:0.3
实际和:0.30000000000000004
和不等于0.3</code>
Nach dem Login kopieren
Nach dem Login kopieren

Das Ergebnis 0,30000000000000004 verdeutlicht den Rundungsfehler, der durch die binäre Darstellung verursacht wird. Selbst geringfügige Unterschiede können in kritischen Systemen zu großen Problemen führen.


So vermeiden Sie Genauigkeitsverluste

1. Verwenden Sie BigDecimal für präzise Berechnungen

Die BigDecimal-Klasse in Java bietet Arithmetik mit beliebiger Genauigkeit und eignet sich daher ideal für Szenarien, die eine hohe Präzision erfordern (z. B. Finanzberechnungen).

Beispiel mit BigDecimal:

<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>
Nach dem Login kopieren
Nach dem Login kopieren

Ausgabe:

<code>预期和:0.3
实际和:0.3
和等于0.3</code>
Nach dem Login kopieren

Durch die Verwendung von BigDecimal werden Präzisionsprobleme beseitigt und Vergleiche führen zu korrekten Ergebnissen.

2. Verwenden Sie zum Vergleich den Epsilon-Wert

Eine andere Möglichkeit, mit Präzisionsverlusten umzugehen, besteht darin, Gleitkommazahlen mit einer Toleranz (Epsilon) zu vergleichen. Diese Methode prüft, ob die Zahlen „nahe genug“ liegen, anstatt sich auf exakte Gleichheit zu verlassen.

Beispiel mit Epsilon-Vergleich:

<code class="language-java">public class EpsilonComparison {
    public static void main(String[] args) {
        double num1 = 0.1;
        double num2 = 0.2;
        double sum = num1 + num2;
        double epsilon = 1e-9; // 定义一个小的容差值

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

        // 使用epsilon进行比较
        if (Math.abs(sum - 0.3) < epsilon) {
            System.out.println("和大约等于0.3");
        } else {
            System.out.println("和不等于0.3");
        }
    }
}</code>
Nach dem Login kopieren

Ausgabe:

<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>
Nach dem Login kopieren
Nach dem Login kopieren

Warum Epsilon zum Vergleichen verwenden?

  • Flexibilität : Es ermöglicht kleine Unterschiede, die durch den Inkorporationsfehler verursacht werden.
  • Einfach
  • : Diese Methode erfordert keine externen Bibliotheken und die Effizienz ist hoch.
Verwenden Sie Apache Commons Mathematik, um die Genauigkeit
zu verbessern

Apache Commons Math ist eine Bibliothek für komplexes mathematisches Computer. Obwohl es keine willkürliche Genauigkeitsarithmetik wie BigDecimal liefert, bietet es praktische Verfahren, die numerische Operationen vereinfachen und in einigen Fällen die Floating -Punkte -Fehler minimieren.

Beispiel: Verwenden Sie Precision.equals, um

zu vergleichen

Ausgabe:
<code>预期和:0.3
实际和:0.30000000000000004
和不等于0.3</code>
Nach dem Login kopieren
Nach dem Login kopieren

Warum sollten Sie Apache Commons Math verwenden?

<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>
Nach dem Login kopieren
Nach dem Login kopieren

vereinfachtes Vergleich

: precision.equals ermöglicht die Verwendung des angegebenen Toleranten mit der angegebenen Toleranz, um den Inkorporationsfehler einfach zu verarbeiten.
  • Leichtes : Die Bibliothek bietet Tools, die sich auf numerische Berechnungen konzentrieren, ohne die Kosten für BigDecimal zu erhöhen.
  • Zusammenfassung
  • Verständnis der Begrenzung
: Das Doppel selbst ist nicht defekt, sondern weil seine binäre schwimmende Punktdarstellung nicht für Aufgaben mit hoher Präzision geeignet ist.

BigDecimal

: BigDecimal kann die Genauigkeit sicherstellen, kann jedoch die Leistung für finanzielle oder kritische Berechnungen beeinflussen.
  • Verwenden von Bibliothek : Apache Commons Math bietet praktische Programme wie Precision.equals, die den Vergleich des schwebenden Punktes effektiv verarbeiten können.
  • Durch das Verständnis von Double und seinen Alternativen können Sie robustere und genauere Java -Anwendungen schreiben.
  • Wenn Sie auf die Genauigkeit des Doppels stoßen und wie Sie diese Probleme lösen können, sagen Sie es mir bitte in den Kommentaren! ?

Das obige ist der detaillierte Inhalt vonWarum doppelt doppelt Präzision verliert und wie man es in Java vermeidet. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage