2012-03-28 16 views
10

Mein Kollege hat dieses Experiment:Doppel Subtraktion Präzision Ausgabe

public class DoubleDemo { 

     public static void main(String[] args) { 
      double a = 1.435; 
      double b = 1.43; 
      double c = a - b; 
      System.out.println(c); 
     } 
} 

Für diese erste Klasse Operation ich diesen Ausgang erwartet:

0.005 

Aber ganz unerwartet die Ausgabe war:

0.0050000000000001155 

Warum scheitert Doppel in solch einer einfachen Operation? Und wenn double nicht der Datentyp für diese Arbeit ist, was sollte ich verwenden?

+0

Vielen Dank für Ihren Erfahrungsaustausch. +1 – kasavbere

+0

Ich bin sicher, das ist ein Duplikat –

+0

mögliche Duplikat von [Retain Präzision mit Doppel in Java] (http://stackoverflow.com/questions/322749/retain-precision-with-doubles-in-java) –

Antwort

17

double intern als eine Fraktion in binären gespeichert wird - wie 1/4 + 1/8 + 1/16 + ...

Der Wert 0.005 - oder der Wert 1.435 - kann nicht als exakte Anteil in binärer gespeichert werden, so kann die genaue double lagern Wert 0.005, und der subtrahierte Wert ist nicht ganz genau. Wenn Sie sich für eine genaue Dezimalarithmetik interessieren, verwenden Sie BigDecimal.

Sie können auch this article nützliche lesen.

+0

+ 1 Verwenden Sie BigDecimal oder runden Sie Ihr Ergebnis ab. –

2

double und float sind nicht genau reelle Zahlen.

Es gibt unendlich viele reelle Zahlen in jedem Bereich, aber nur endliche Anzahl von Bits, um sie darzustellen! Aus diesem Grund werden Rundungsfehler für Double und Floats erwartet.

Die Nummer, die Sie erhalten, ist die größtmögliche Anzahl, die in Floating Point-Darstellung durch Doppel dargestellt werden kann.

Für weitere Details lesen Sie bitte this article [Warnung: möglicherweise High-Level].

Sie könnten BigDecimal verwenden, um genau eine Dezimalzahl zu erhalten [aber Sie werden erneut Rundungsfehler auftreten, wenn Sie versuchen, 1/3 zu erhalten].

1

double und float Arithmetik wird wegen der Rundung, die "unter der Haube" vorkommt, nie genau richtig sein.

Im Wesentlichen Doppelgänger und Schwimmer können eine unendliche Anzahl von Dezimalzahlen haben, aber im Speicher müssen sie durch eine reelle Anzahl von Bits dargestellt werden. Wenn Sie diese Dezimalarithmetik ausführen, tritt eine Rundungsprozedur auf und ist oft um einen sehr kleinen Betrag deaktiviert, wenn Sie alle Dezimalstellen berücksichtigen.

Wie bereits erwähnt, wenn Sie vollständig genaue Werte benötigen, verwenden Sie BigDecimal, die ihre Werte unterschiedlich speichert. Here's the API

+0

Es ist nicht richtig zu sagen, dass sie "nie" genau richtig sein werden. Es wäre richtig zu sagen, dass sie niemals genau richtig sein werden, wenn sie etwas anderes als Brüche repräsentieren, deren Nenner keine Zweierpotenz ist. – supercat

-1
//just try to make a quick example to make b to have the same precision as a has, by using BigDecimal 

private double getDesiredPrecision(Double a, Double b){ 
    String[] splitter = a.toString().split("\\."); 
    splitter[0].length(); // Before Decimal Count 
    int numDecimals = splitter[1].length(); //After Decimal Count 

    BigDecimal bBigDecimal = new BigDecimal(b); 
    bBigDecimal = bBigDecimal.setScale(numDecimals,BigDecimal.ROUND_HALF_EVEN); 

    return bBigDecimal.doubleValue(); 
} 
+0

Das beantwortet die Frage nicht. –

+0

Nun, Sie haben Recht. Versuchen Sie, ein kleines Beispiel auf BigDecimal zu geben. Es gibt bereits Leute, die die Frage beantworten. Keine Notwendigkeit, sich zu wiederholen. – madmaximshen

+0

Auf SO sind die Antworten für die Bereitstellung einer vollständigen, in sich geschlossenen Antwort. Wenn Sie der Meinung sind, dass etwas in einer anderen Antwort fehlt, hinterlassen Sie einen Kommentar, sobald Sie genug Reputation haben. Wenn Sie denken, dass Sie eine bessere * vollständige * Antwort schreiben können, tun Sie das. Schreibe keine "halben Antworten" wie diese. –