Wat ik zou willen is een methode om een dubbel getal om te zetten naar een string die afrondt met de half-omhoog methode - d.w.z. als het af te ronden decimaal getal 5 is, wordt altijd naar boven afgerond naar het volgende getal. Dit is de standaard afrondingsmethode die de meeste mensen in de meeste situaties verwachten.
Ik wil ook graag dat alleen significante cijfers worden weergegeven - d.w.z. dat er geen nullen achteraan mogen staan.
Ik weet dat een methode om dit te doen is om de String.format
methode te gebruiken:
String.format("%.5g%n", 0.912385);
retourneert:
0.91239
wat geweldig is, maar het geeft altijd getallen weer met 5 decimalen, zelfs als ze niet significant zijn:
String.format("%.5g%n", 0.912300);
geeft terug:
0.91230
Een andere methode is het gebruik van de DecimalFormatter
:
DecimalFormat df = new DecimalFormat("#.#####");
df.format(0.912385);
retourneert:
0.91238
Maar zoals je kunt zien wordt er gebruik gemaakt van half-even afronding. Dat wil zeggen dat het naar beneden afrondt als het vorige cijfer even is. Wat ik zou willen is het volgende:
0.912385 -> 0.91239
0.912300 -> 0.9123
Wat is de beste manier om dit in Java te bereiken?
Gebruik setRoundingMode
, stel de RoundingMode
expliciet in om uw probleem met de half-even ronde op te lossen, gebruik dan het opmaakpatroon voor uw gewenste uitvoer.
Voorbeeld:
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));
}
geeft de uitvoer:
12
123.1235
0.23
0.1
2341234.2125
EDIT: Het oorspronkelijke antwoord gaat niet in op de nauwkeurigheid van de dubbele waarden. Dat is prima als het je niet veel kan schelen of het naar boven of beneden afrondt. Maar als je nauwkeurige afronding wilt, dan moet je rekening houden met de verwachte nauwkeurigheid van de waarden. Floating point waarden hebben intern een binaire representatie. Dat betekent dat een waarde als 2.77395 intern niet exact die waarde heeft. Hij kan iets groter of iets kleiner zijn. Als de interne waarde iets kleiner is, dan zal het niet afronden naar 2.7740. Om die situatie te verhelpen, moet u zich bewust zijn van de nauwkeurigheid van de waarden waarmee u werkt, en die waarde optellen of aftrekken alvorens af te ronden. Als u bijvoorbeeld weet dat uw waarden tot op 6 cijfers nauwkeurig zijn, dan moet u, om halverwege naar boven af te ronden, die nauwkeurigheid bij de waarde optellen:
Double d = n.doubleValue() + 1e-6;
Om naar beneden af te ronden, trek je de nauwkeurigheid af.
Ervan uitgaande dat waarde
een dubbeltje
is, kun je:
(double)Math.round(value * 100000d) / 100000d
Dat's voor 5 cijfers precisie. Het aantal nullen geeft het aantal decimalen aan.