2017-02-12 5 views
1

Diese Frage bezieht sich auf this one und viele andere, aber kein Duplikat. Ich arbeite mit double s, die sicherlich richtig sind 6 Dezimalstellen zu sagen undNächste Runde auf Fließkomma-Rundung

String.format("%f.6", x) 

liefert immer den richtigen Wert verwenden.

String.valueOf(x) 

nicht. Ich müsste "x" runden, so dass es die gleiche (oder im Fall von abschließenden Nullen kürzere) Ausgabe als Formatierung auf 6 Dezimalstellen ergeben würde. Ich möchte nicht die genaue Darstellung der Dezimalzahl und ich weiß, dass es nicht existiert.

x = Double.parseDouble(String.format("%.6f", x)) 

Verwendung gibt mir, was ich will, aber ich bin für einige einfachere Methode (schneller und produzieren keinen Müll) suchen. Der offensichtliche Weg

x = 1e-6 * Math.round(1e6 * x) 

tut nicht Arbeit für die Rundung.


Als Beispiel betrachten wir die snipped folgenden

double wanted = 0.07; 
double given = 0.07000000455421122; 
double wrong = 1e-6 * Math.round(1e6 * given); 
double slow = Double.parseDouble(String.format("%.6f", given)); 
double diff = wrong - wanted; 
double ulp = Math.ulp(wrong); 

Berechnung dieser Werte

wanted 0.07 
given 0.07000000455421122 
wrong 0.06999999999999999 
slow 0.07 
diff -1.3877787807814457E-17 
ulp 1.3877787807814457E-17 

Das Problem scheint zu sein, dass 1e-6 * 70000 das bestmögliche Ergebnis produziert, aber es ist ein ULP weg von was ich möchte.

Noch einmal: Ich frage nicht, wie man umrundet, ich frage, wie man es schneller macht. Also ich habe Angst, BigDecimal ist nicht der Weg zu gehen.

+1

Sorry, aber angesichts der Tatsache, dass 'BigDecimal' eine Methode hat, die genau das tut, was Sie fragen, verstehe ich nicht, warum diese Option vom Tisch ist. –

+0

'double' kann nicht genau '0,07' darstellen. Das Beste, was Sie erreichen können, ist '0.070000000000000007', und dafür können Sie einfach' double wollte = int (gegeben * 100)/100.0'. –

+0

@JoeC Geschwindigkeit (und produzierte Müll). In meinem echten Anwendungsfall spielt das keine Rolle, aber ich bin neugierig. – maaartinus

Antwort

3

Das Problem ist, dass 1e-6 ist nicht genau 10 -6 (es ist in der Tat 0.000000999999999999999954748111825886258685613938723690807819366455078125)

stattdessen durch diese zu multiplizieren, indem man 1e6 teilen soll, die genau 10 , dann ist das Ergebnis wird die nächste Fließkommazahl zu 0,07 sein (das ist 0.07 oder 0.070000000000000006661338147750939242541790008544921875).

+0

WOW! Wirklich so einfach? – maaartinus