Bewahren Sie Präzision mit Double in Java
public class doublePrecision {
public static void main(String[] args) {
double total = 0;
total += 5.6;
total += 5.8;
System.out.println(total);
}
}
Der obige code druckt:
11.399999999999
Wie würde ich diese bekommen nur drucken (oder in der Lage sein, es zu benutzen, wie) 11.4?
InformationsquelleAutor der Frage Deinumite | 2008-11-27
Du musst angemeldet sein, um einen Kommentar abzugeben.
Wie andere erwähnt haben, werden Sie wahrscheinlich wollen, verwenden Sie die
BigDecimal
Klasse, wenn Sie wollen, um eine genaue Darstellung 11.4.Nun, eine kleine Erklärung, warum dies geschieht:
Den
float
unddouble
primitiven Typen in Java sind Gleitkomma zahlen, wo die Zahl gespeichert ist, als eine binäre Darstellung für einen Bruchteil und einem Exponenten.Genauer gesagt, eine double-precision-floating-point-Wert wie die
double
Typ ist ein 64-bit-Wert, wobei:Diese Teile werden kombiniert, um zu produzieren ein
double
Darstellung eines Werts.(Quelle: Wikipedia: Doppelter Genauigkeit)
Für eine detaillierte Beschreibung, wie floating-point-Werte behandelt werden, die in Java finden Sie in der Abschnitt 4.2.3: Floating-Point-Typen, Formate und Werte der Java Language Specification.
Den
byte
char
int
long
Arten sind fixed-point zahlen, die genaue representions von zahlen. Im Gegensatz zu fixed-point-zahlen, Gleitkomma-zahlen wird einige Male (sicher davon ausgehen, dass "die meiste Zeit") nicht in der Lage sein, um eine genaue Darstellung einer Zahl. Dies ist der Grund, warum Sie am Ende mit11.399999999999
als Ergebnis5.6 + 5.8
.Wenn die eine Wert das genau ist, wie 1.5 oder 150.1005, werden Sie wollen, um die Verwendung eines fixed-point-Typen, die in der Lage sein zu vertreten, die Zahl genau.
Wie bereits erwähnt, schon mehrmals, Java hat eine
BigDecimal
Klasse, die Handhabung sehr große zahlen und sehr kleine zahlen.Aus der Java-API-Referenz für die
BigDecimal
Klasse:Es wurde viele Fragen auf Stack Overflow im Zusammenhang mit der Angelegenheit von floating-point-zahlen und seine Präzision. Hier ist eine Liste von Fragen, die von Interesse sein können:
Wenn Sie wirklich wollen, um sich nach unten zu der nitty gritty details von floating-point-zahlen, werfen Sie einen Blick auf Was Jeder Computer Scientist Should Know About Floating-Point Arithmetic.
InformationsquelleAutor der Antwort coobird
Wenn Sie die Eingabe einer double-Zahl, zum Beispiel
33.33333333333333
der Wert, den Sie bekommen, ist eigentlich die nächstgelegene Darstellbare double-precision-Wert, genau:Dividieren durch 100 gibt:
dem auch ist nicht darstellbar als Zahl mit doppelter Genauigkeit, so ist es wieder gerundet auf den nächsten darstellbaren Wert, das ist genau das:
Beim drucken von diesem Wert aus, es wird gerundet noch einmal auf 17 Dezimalstellen geben:
InformationsquelleAutor der Antwort Stephen Canon
Wenn Sie nur wollen, um Prozess-Werte als Bruchteile, die Sie erstellen können, einen Bruchteil der Klasse die hat einen Zähler und Nenner Feld.
Write-Methoden für das hinzufügen, subtrahieren, multiplizieren und dividieren sowie eine Methode toDouble. Auf diese Weise können Sie vermeiden, schwimmt während der Berechnungen.
EDIT: Schnelle Umsetzung,
InformationsquelleAutor der Antwort Viral Shah
Beachten Sie, dass Sie würde das gleiche problem haben, wenn Sie begrenzt-Nachkommastellen rechnen und umgehen wollte mit 1/3: 0.333333333 * 3 0.999999999, nicht 1.00000000.
Leider, 5.6, 5.8 und 11.4 sind nicht nur Runde zahlen in binäre, denn Sie beinhalten Fünftel. Also der float-Darstellung von Ihnen nicht genau, nur als 0.3333 nicht genau 1/3.
Wenn alle zahlen, die Sie verwenden, sind nicht-wiederkehrende Dezimalzahlen, und Sie wollen genaue Ergebnisse zu erzielen, verwenden BigDecimal. Oder wie schon andere gesagt haben, wenn deine Werte sind wie Geld in dem Sinne, dass Sie alle ein Vielfaches von 0.01 oder 0.001, oder so etwas, dann multiplizieren Sie alles, um einen festen Strom von 10 und mit int oder long (addition und Subtraktion sind trivial: watch out für Multiplikation).
Jedoch, wenn Sie glücklich sind mit binären für die Berechnung, aber Sie nur drucken wollen, die Dinge in eine etwas freundlichere format, versuchen Sie
java.util.Formatter
oderString.format
. In den format-string angeben, a Präzision, die weniger als die volle Genauigkeit von ein double. 10 bedeutende zahlen, sagen, 11.399999999999 ist 11.4, so das Ergebnis wird fast so präzise und mehr Menschen lesbaren in Fällen, in denen das binäre Ergebnis ist sehr nahe an einem Wert erfordert nur ein paar Nachkommastellen.Die Genauigkeit angeben, hängt ein bisschen auf, wie viel Mathematik Sie haben Ihre zahlen - in der Regel je mehr Sie tun, desto mehr Fehler sammeln sich, aber manche algorithmen, sammeln Sie viel schneller, als die anderen (Sie heißen "instabil" statt "stabil" in Bezug auf Rundungsfehler). Wenn alles, was Sie tun, ist das hinzufügen von ein paar Werte, dann würde ich sagen, die fallen nur mit einer Nachkommastelle präzise werden die Dinge. Experiment.
InformationsquelleAutor der Antwort Steve Jessop
Möchten Sie vielleicht zu suchen in der Verwendung von java ist java.math.BigDecimal Klasse, wenn Sie wirklich brauchen, präzisionsberechnungen. Hier ist ein guter Artikel von Oracle/Sun auf der Fall ist für BigDecimal. Sie können zwar niemals 1/3 als jemand erwähnt, Sie kann die macht haben, zu entscheiden, genau, wie präzise Sie wollen das Ergebnis zu sein. setScale() ist dein Freund.. 🙂
Ok, denn ich habe viel zu viel Zeit auf meinen Händen im moment ist hier ein code-Beispiel, das bezieht sich auf deine Frage:
und plug meine neue Lieblings-Sprache Groovy, hier ist ein genauerer Beispiel für die gleiche Sache:
InformationsquelleAutor der Antwort Vinny
Wie andere bemerkt haben, nicht alle Dezimalzahlen dargestellt werden können als binäre seit dezimal basiert auf Potenzen von 10 und binary basiert auf Potenzen von zwei.
Wenn Präzision ankommt, BigDecimal verwenden, aber wenn Sie wollen einfach nur freundlich Ausgang:
Geben Sie:
InformationsquelleAutor der Antwort Draemon
Ziemlich sicher, dass Sie könnte es geschafft haben, in einer Linie drei Beispiel. 🙂
Wenn Sie möchten, genauen Präzision, BigDecimal verwenden. Andernfalls können int-Werte multipliziert mit 10 ^ was Präzision, die Sie wollen.
InformationsquelleAutor der Antwort Dustin
Läufst du gegen die Präzision Beschränkung von Typ double.
Java.Mathematik hat einige beliebiger Genauigkeit arithmetische Einrichtungen.
InformationsquelleAutor der Antwort John
Können Sie nicht, weil 7.3 nicht haben eine endliche Darstellung in Binär. Die nächstgelegene Sie bekommen können 2054767329987789/2**48 = 7.3+1/1407374883553280.
Werfen Sie einen Blick auf http://docs.python.org/tutorial/floatingpoint.html für eine weitere Erklärung. (Es ist auf der Python-website, aber Java und C++ haben das gleiche "problem".)
Die Lösung hängt davon ab, was genau dein problem ist:
InformationsquelleAutor der Antwort dan04
InformationsquelleAutor der Antwort sravan
Verwendung von java.math.BigDecimal
Doubles sind binäre Fraktionen intern, so dass Sie manchmal nicht darstellen Dezimalbrüche um die genauen dezimal.
InformationsquelleAutor der Antwort Kevin Crowell
Multiplizieren Sie alles mit 100 und speichern Sie es in eine lange Cent.
InformationsquelleAutor der Antwort Paul Tomblin
Computer speichern zahlen in Binär und kann nicht wirklich zahlen wie 33.333333333 oder 100.0 genau. Dies ist eines der schwierigen Dinge über die Verwendung von doubles. Sie haben gerade mal um die Antwort, Ehe er es an einen Benutzer. Zum Glück in den meisten Anwendungen, die Sie nicht benötigen, dass viele Dezimalstellen gerundet, wie auch immer.
InformationsquelleAutor der Antwort Jay Askren
Floating-point-zahlen unterscheiden sich von den reellen zahlen in sich, dass für beliebige floating-point-Zahl gibt es eine nächst höhere floating-point-Zahl. Gleich als ganze zahlen. Es gibt keine ganze Zahl zwischen 1 und 2.
Gibt es keine Methode zur Darstellung von 1/3 als float. Es gibt ein Schwimmer unten und es ist ein schweben über es, und es gibt eine gewisse Distanz zwischen Ihnen. Und 1/3 ist in diesem Raum.
Apfloat für Java-Forderungen für die Arbeit mit beliebiger Genauigkeit Gleitkomma-zahlen, aber ich habe es nie benutzt. Vermutlich einen Blick Wert.
http://www.apfloat.org/apfloat_java/
Eine ähnliche Frage wurde hier vor
Java floating-point-high-precision-Bibliothek
InformationsquelleAutor der Antwort Spike
Verdoppelt werden Annäherungen der Dezimalzahlen in Ihre Java-Quellcode. Sehen Sie die Folge der Diskrepanz zwischen der Doppel - (was ist ein Binär codierter Wert) und Ihre Quelle (das ist dezimal codiert).
Java produziert die nächste binäre Annäherung. Sie können die java.text.DecimalFormat anzeigen, um eine besser aussehende decimal-Wert.
InformationsquelleAutor der Antwort S.Lott
Verwenden Sie ein BigDecimal. Sie können auch angeben, Rundungsregeln (wie ROUND_HALF_EVEN, die Minimierung der statistischen Fehler durch die Rundung auf die sogar die Nachbarn, wenn beide gleich weit entfernt sind; d.h. die beiden 1,5-und 2,5-Runde 2).
InformationsquelleAutor der Antwort Adam Jaskiewicz
Check-out BigDecimal, es behandelt Probleme im Umgang mit Gleitkomma-Arithmetik so.
Wird der neue Aufruf würde wie folgt Aussehen:
Verwenden, setScale (), um die Anzahl der Dezimalstelle Genauigkeit verwendet werden.
InformationsquelleAutor der Antwort Dark Castle
Warum nicht verwenden Sie die round () - Methode aus der Klasse Math?
InformationsquelleAutor der Antwort Mr.Cat
Wenn Sie haben keine andere Wahl, als mit double-Werte verwenden Sie den folgenden code.
InformationsquelleAutor der Antwort user5734382
Vergeuden Sie nicht Ihre efford Verwendung von BigDecimal. In 99.99999% der Fälle brauchst du es nicht. java Doppel - Typ ist natürlich Ungefähre, aber in fast allen Fällen, es ist ausreichend präzise. Daran, dass Ihr ein Fehler an der 14th signifikante Ziffer. Das ist wirklich vernachlässigbar!
Um schöne Ausgabe verwenden:
InformationsquelleAutor der Antwort Maciek D.