Java Float runden und an PreparedStatement übergeben

jimb0p

Erfahrenes Mitglied
Hallo Zusammen,

ich habe folgende Funktion:

Java:
public float roundFloatNumber(float value){
        DecimalFormat df = new DecimalFormat();
        df.setMinimumFractionDigits(2);
        df.setMaximumFractionDigits(2);
        return Float.parseFloat(df.format(value).replace(",", "."));
    }

Die benutze ich damit mir jeder Float Wert gerundet wird. Das funktioniert auch fehlerfrei. Wenn ich mir den gerundeten Wert ausgeben lasse mit System.out.print bekomme ich ein korrektes Ergebnis. Wenn ich nun aber den Rückgabewert der Funktion an einem PreparedStatement mittels rs.setFloat übergebe, bekomme ich einen Wert mit 12 Nachkommastellen. Übergebe ich den Wert stattdessen mit

Java:
pStmnt.setString(8, String.valueOf(fPreisGesamt));

kommt in der Datenbank der korrekte Wert an. Mich würde interessieren warum das so ist und wie man das korrekt macht.

Grüße!
 

sheel

I love Asm
Hi

die 12 Nachkommastellen siehst du dann als DB-Inhalt (oder?), mit welchem Programm?
Und wie schaut so eine 12stellige Zahl zB. aus?
 
Zuletzt bearbeitet:

jimb0p

Erfahrenes Mitglied
ja genau. Beispielwert: 151,759994506836
Es ist eine MSSQL DB und ich sehe es mit dem Management Studio 2012
 

sheel

I love Asm
Und gedacht war vermutlich 151.76? Das ist (leider) normal.

Kommazahlen im Binärformat sind prinzipiell etwas problematisch. zB. weißt du sicher, dass 1010b = 8*1 + 4*0 + 2*1 + 1*0 = 10 ist, weil die "Stellenwerte" "...32 16 8 4 2 1" sind. Das Problem ist, auf der anderen Seite vom Komma ist keine abgetrennte normale Binärzahl, sonern die Stellewerte gehen weiter 1/2 1/4 1/8 ... also 0.25 0.125 0.0625 usw.

Wenn man 0.76 jetzt durch eine Summe von solchen Zweierpotenzbrüchen darzustellen will kommt man drauf, dass man unendlich viele Binärkommastellen bekommt.

Die übliche IEEE754-Speicherart für float/double in heutigen Computern macht das mit den Kommastellen genau so wie beschrieben, und kann ein 0.76 deshalb nicht eindeutig speichern. 0.759994506836 dürfte das Beste sein, was mit den vorhandenen Bit in einem float möglich ist.
Als zusätzliches Problem gibt es in IEEE754 noch einige Wahlmöglichkeiten, wie sehr der Prozessor und Software (wie die JVM) die hintersten Bits bei jeder Operation ignorieren/wegrunden dürfen.

String.valueOf setzt es als 0.76 in die Deziamlform um, dieses ManagementStudio wohl nicht, und ruft auch keine Rundungsfunktion vor der Ausgabe auf. ... Wenn die genauen Kommastellen wichtig sind muss der Wert als String in die Datenbank (also auch der Spaltendatentyp usw.), sonst kann man sich einfach nicht darauf verlassen.