Det jeg ønsker er en metode for å konvertere en dobbel til en streng som avrunder ved hjelp av half-up-metoden - dvs. hvis desimaltallet som skal avrundes er 5, avrundes det alltid opp til neste tall. Dette er standardmetoden for avrunding de fleste forventer i de fleste situasjoner.
Jeg vil også at bare signifikante sifre skal vises - dvs. at det ikke skal være noen nuller bak.
Jeg vet at en metode for å gjøre dette er å bruke metoden String.format
:
String.format("%.5g%n", 0.912385);
returnerer:
0.91239
som er flott, men den viser alltid tall med 5 desimaler selv om de ikke er signifikante:
String.format("%.5g%n", 0.912300);
returnerer:
0.91230
En annen metode er å bruke DecimalFormatter
:
DecimalFormat df = new DecimalFormat("#.#####");
df.format(0.912385);
returnerer:
0.91238
Men som du kan se, bruker dette halv jevn avrunding. Det vil si at det avrundes nedover hvis det forrige sifferet er partall. Det jeg vil ha er dette:
0.912385 -> 0.91239
0.912300 -> 0.9123
Hva er den beste måten å oppnå dette på i Java?
Bruk setRoundingMode
, angi RoundingMode
eksplisitt for å håndtere problemet ditt med den halv-jevne runden, og bruk deretter formatmønsteret for ønsket utdata.
Eksempel:
DecimalFormat df = new DecimalFormat("#.####");
df.setRoundingMode(RoundingMode.CEILING);
for (Number n : Arrays.asList(12, 123.12345, 0.23, 0.1, 2341234.212431324)) {
Double d = n.doubleValue();
System.out.println(df.format(d));
}
gir resultatet:
12
123.1235
0.23
0.1
2341234.2125
EDIT: Det opprinnelige svaret tar ikke for seg nøyaktigheten til de doble verdiene. Det er greit hvis du ikke bryr deg så mye om det avrundes opp eller ned. Men hvis du vil ha nøyaktig avrunding, må du ta hensyn til den forventede nøyaktigheten til verdiene. Flytende punktverdier har en binær representasjon internt. Det betyr at en verdi som 2,77395 faktisk ikke har den eksakte verdien internt. Den kan være litt større eller litt mindre. Hvis den interne verdien er litt mindre, vil den ikke rundes opp til 2,7740. For å avhjelpe denne situasjonen må du være klar over nøyaktigheten til verdiene du arbeider med, og legge til eller trekke fra denne verdien før du avrunder. Når du for eksempel vet at verdiene dine er nøyaktige opp til 6 sifre, legger du denne nøyaktigheten til verdien for å runde opp halvveisverdier:
Double d = n.doubleValue() + 1e-6;
For å avrunde nedover trekker du fra nøyaktigheten.