Ich muss einige Gleitkommavariablen berechnen und mein Kollege schlägt mir vor, sie BigDecimal
stattdessen zu verwenden, double
da sie genauer sind. Aber ich möchte wissen, was es ist und wie ich das Beste daraus machen kann BigDecimal
?
java
floating-point
double
bigdecimal
Truong Ha
quelle
quelle
Antworten:
A
BigDecimal
ist eine exakte Art, Zahlen darzustellen. ADouble
hat eine gewisse Präzision. Das Arbeiten mit Doppelwerten verschiedener Größen (z. B.d1=1000.0
undd2=0.001
) kann dazu führen0.001
, dass beim Summieren insgesamt ein Abfall auftritt, da der Größenunterschied so groß ist. DamitBigDecimal
würde das nicht passieren.Der Nachteil
BigDecimal
ist , dass es langsamer, und es ist ein bisschen schwieriger zu Programmalgorithmen auf diese Weise (wegen+
-
*
und/
nicht überlastet wird).Wenn Sie mit Geld zu tun haben oder Präzision ein Muss ist, verwenden Sie
BigDecimal
. AnsonstenDoubles
neigen sie dazu, gut genug zu sein.Ich empfehle das Javadoc von zu lesen,
BigDecimal
da sie die Dinge besser erklären als ich hier :)quelle
if (Math.abs(loadPerServer - maxLoadPerServer) < 0.000001d) {
BigDecimal
", hätte ein Double mehr "Präzision" (mehr Ziffern).Mein Englisch ist nicht gut, deshalb schreibe ich hier nur ein einfaches Beispiel.
Programmausgabe:
Möchte noch jemand double verwenden? ;)
quelle
System.out.println(0.003f - 0.002f);
BigDecimal ist genau:System.out.println(new BigDecimal("0.003").subtract(new BigDecimal("0.002")));
Es gibt zwei Hauptunterschiede zum Doppel:
Der Grund, warum Sie BigDecimal für Geldberechnungen verwenden sollten, ist nicht, dass es eine beliebige Zahl darstellen kann, sondern dass es alle Zahlen darstellen kann, die in Dezimalzahlen dargestellt werden können und praktisch alle Zahlen in der Geldwelt enthalten (Sie überweisen niemals 1/3 $ für jemanden).
quelle
Wenn Sie einen Bruchwert wie einen
1 / 7
Dezimalwert aufschreiben, erhalten Siemit einer unendlichen Folge von
142857
. Da Sie nur eine endliche Anzahl von Ziffern schreiben können, wird zwangsläufig ein Rundungs- (oder Kürzungs-) Fehler auftreten.Zahlen wie
1/10
oder1/100
ausgedrückt als Binärzahlen mit einem Bruchteil haben auch eine unendliche Anzahl von Stellen nach dem Dezimalpunkt:Doubles
Speichern Sie Werte als binär und führen Sie daher möglicherweise einen Fehler ein, indem Sie eine Dezimalzahl in eine Binärzahl konvertieren, ohne eine Arithmetik durchzuführen.Dezimalzahlen (wie
BigDecimal
) hingegen speichern jede Dezimalstelle unverändert. Dies bedeutet, dass ein Dezimaltyp im Allgemeinen nicht genauer ist als ein binärer Gleitkomma- oder Festkommatyp (dh er kann nicht1/7
ohne Genauigkeitsverlust gespeichert werden), aber er ist genauer für Zahlen mit einer endlichen Anzahl von Dezimalstellen als ist häufig bei Geldberechnungen der Fall.Java
BigDecimal
hat den zusätzlichen Vorteil, dass es auf beiden Seiten des Dezimalpunkts eine beliebige (aber endliche) Anzahl von Stellen haben kann, die nur durch den verfügbaren Speicher begrenzt ist.quelle
BigDecimal ist die numerische Bibliothek von Oracle mit beliebiger Genauigkeit. BigDecimal ist Teil der Java-Sprache und eignet sich für eine Vielzahl von Anwendungen, die von finanziell bis wissenschaftlich reichen (genau dort bin ich).
Es ist nichts Falsches daran, für bestimmte Berechnungen Doppel zu verwenden. Angenommen, Sie wollten Math.Pi * Math.Pi / 6 berechnen, dh den Wert der Riemann-Zeta-Funktion für ein reales Argument von zwei (ein Projekt, an dem ich gerade arbeite). Die Gleitkommadivision stellt Sie vor ein schmerzhaftes Problem mit Rundungsfehlern.
BigDecimal hingegen enthält viele Optionen zum Berechnen von Ausdrücken mit beliebiger Genauigkeit. Die in der folgenden Oracle-Dokumentation beschriebenen Methoden zum Hinzufügen, Multiplizieren und Teilen "ersetzen" von +, * und / oder in BigDecimal Java World:
http://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html
Die compareTo-Methode ist besonders nützlich in while- und for-Schleifen.
Seien Sie jedoch vorsichtig bei der Verwendung von Konstruktoren für BigDecimal. Der String-Konstruktor ist in vielen Fällen sehr nützlich. Zum Beispiel der Code
BigDecimal onethird = new BigDecimal ("0.33333333333");
verwendet eine Zeichenfolgendarstellung von 1/3, um diese sich unendlich wiederholende Zahl mit einem bestimmten Genauigkeitsgrad darzustellen. Der Rundungsfehler liegt höchstwahrscheinlich irgendwo so tief in der JVM, dass die Rundungsfehler die meisten Ihrer praktischen Berechnungen nicht stören. Ich habe jedoch aus persönlicher Erfahrung gesehen, wie sich eine Abrundung eingeschlichen hat. Die setScale-Methode ist in dieser Hinsicht wichtig, wie aus der Oracle-Dokumentation hervorgeht.
quelle
/* * Portions Copyright IBM Corporation, 2001. All Rights Reserved. */
Wenn Sie sich mit Berechnungen beschäftigen, gibt es Gesetze, wie Sie berechnen und welche Genauigkeit Sie verwenden sollten. Wenn Sie dies nicht tun, werden Sie etwas Illegales tun. Der einzige wirkliche Grund ist, dass die Bitdarstellung von Dezimalfällen nicht präzise ist. Wie Basil einfach ausgedrückt hat, ist ein Beispiel die beste Erklärung. Um sein Beispiel zu ergänzen, passiert Folgendes:
Ausgabe:
Auch das haben wir:
Gibt uns die Ausgabe:
Aber:
Hat die Ausgabe:
quelle