2010-08-09 12 views
6

Angesichts der folgenden Code würde ich erwarten, dass es "float = 32000.0001" zurückgibt. Stattdessen gibt es "float = 32000.0" zurück.Runden in Java Float.parseFloat

System.out.println("float = "+Float.parseFloat("32000.0001")); 

Gibt es etwas, was ich tun kann, um die Rundung zu verhindern/kontrollieren? Ich möchte den vollen Wert ohne Rundung zurückgegeben.

Antwort

7

Ein Float hat nur 24 Bit Genauigkeit, was nicht ausreicht, um die Anzahl der Stellen in Ihrem Wert zu halten. Die Rundung ist nicht auf die Analyse, sondern auf die Größe der Zahl zurückzuführen. Sie müssen ein Double verwenden, wenn Sie einen Fließkommawert benötigen, oder BigDecimal verwenden, wenn Sie eine beliebige Genauigkeit benötigen.

1

Wenn Dezimalstellen für Sie von Interesse sind, würde ich stark empfehlen BigDecimal stattdessen verwenden.

Wie es ist, ist es nicht ganz klar ist mir (ohne Prüfung), ob das Problem der aus einem String-Parsing ist oder die Formatierung in einen String zurück.

EDIT: In diesem Fall vermute ich stark auf Parsing es Abrunden ... da float nur 7 (garantiert) signifikante Stellen und Sie versuchen, 9.

+0

brach ich die einzige Zeile in mehrere Zeilen und lief er durch den Debugger. Das Problem scheint in der Analyse zu liegen. Es scheint, dass Float.parseFloat auf "32000.0" gerundet wird. – Shane

+0

@Shane: Sie gehen immer noch davon aus, dass der Debugger Ihnen den genauen Wert zeigt, vermute ich. –

+0

Wechsel zu BigDecimal behoben meine Probleme mit Dezimalstellen – jeff

0

zu bewahren Wenn Sie Runden vermeiden wollen, Verwenden Sie BigDecimal. Die primitiven Typen float und double sind schneller, aber sie können nicht viele gemeinsame Dezimalwerte darstellen.

0

Floats und Doubles sind begrenzt. Sie sind nur in der Lage, gebrochene Anteile von Zahlen als eine Summe von zwei Basisfraktionen genau darzustellen. Der Bruchteil kann vollständig als die Summe einiger Serien wie dargestellt werden:

1/2 + 0/4 + 1/8 + 1/16 + ...

Leider gibt es eine große Anzahl von häufig gebrauchte Zahlen, die nie vollständig dargestellt werden, wie:

1/3, 1/7, 1/9, 5/11 usw.

Sie müssen prüfen, ob die Zahl genau, bevor Sie zu kümmern dargestellt werden Rundung. Wenn diese Art von Genauigkeit von äußerster Wichtigkeit ist, dann müssen Sie auf eine Nicht-Float- oder Nicht-Double-Lösung schauen.

Es gibt binäre Dezimalbibliotheken, die solche Berechnungen genau durchführen. Sie neigen dazu, langsamer zu berechnen, da es keine spezialisierte Hardware gibt, um ihre Berechnungen zu beschleunigen. Außerdem nehmen sie mehr Speicher in Anspruch, weil Sie im Wesentlichen eine Ziffernliste speichern.

Nachdem Sie die gewünschte Nummer für das Detail darstellen können, ist eine Rundungslösung einfach. Wahrscheinlich brauchen Sie nicht einmal eine Rundungslösung. weil der Hauptgrund, warum Sie versuchen, in diesem Fall zu runden, der Float ist, der Ihren Wert nicht richtig darstellen kann.

2

Sie müssen sehr vorsichtig sein, wenn Sie Fließkomma beim Schreiben von Software verwenden.
Bestimmte Dezimalzahlen haben keine genaue Basis 2 Darstellungen ist eine Sache zu beachten. 0,1, 0,01, 0,001 sind einige Beispiele. Um diese Zahl in der Basis 2 darzustellen, muss sie also gerundet werden.

Ein anderes Problem ist, dass Sie mit einer endlichen Menge von Bits zu tun haben, um Zahlen darzustellen, und andere Rundungsfehler auftreten können. Je weiter man sich von 0 entfernt, desto mehr Zahlen gibt es, die nicht genau dargestellt werden können, und daher findet eine Rundung statt.

Es gibt einige andere Probleme. Die meisten werden in dem folgenden Papier erwähnt. Für eine formelle Abhandlung siehe: http://www.scribd.com/doc/5836/What-Every-Computer-Scientist-Should-Know-About-FloatingPoint-Arithmetic

Verwenden Sie keine Floats, wo Sie eine genaue Zahl wissen müssen.

1

Wie andere bemerken, float hat unzureichende Genauigkeit, um das volle Ergebnis zu halten. Der BigDecimal(double) Konstruktor ist genau, es ist also eine praktische Möglichkeit, die Darstellung zu sehen:

System.out.println(new BigDecimal(32000.0001f)); // as float 
System.out.println(new BigDecimal(32000.0001d)); // as double 

Welche dies zeigt:

32000 
32000.00010000000111176632344722747802734375 
+0

Wenn Sie es von Text analysieren, sollten Sie den 'BigDecimal (String)' -Konstruktor verwenden; wird noch bessere Präzision geben –

+0

@Sanjay Manohar: Richtig; Dies ist lediglich ein bequemer Weg, um die Dezimaldarstellungen der entsprechenden "float" - und "double" -Werte zu vergleichen. Dieser Rechner ist eine Alternative: http://babbage.cs.qc.edu/IEEE-754/Decimal.html – trashgod