Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DecimalFormat using incorrect RoundingMode even when set explicitly

Why is this DecimalFormat not rounding using RoundingMode.HALF_UP as expected, and what should be done to get the expected output? Can it be done with DecimalFormat?

DecimalFormat df = new DecimalFormat("0.0");

df.setRoundingMode(RoundingMode.HALF_UP);

df.format(0.05); // expecting 0.1, getting 0.1
df.format(0.15); // expecting 0.2, getting 0.1  << unexpected

df.format(0.06); // expecting 0.1, getting 0.0  << unexpected

I have seen the answers from this question, specifically this answer, but it only seems to work when rounding to an integer.

My JDK is 8.0.110 and my JRE is 8.0.730.2

like image 281
4castle Avatar asked Aug 28 '26 03:08

4castle


1 Answers

(Answer below using Java 8.)

The issue you are seeing comes from specifying "0.15" or "0.05" in code, which when represented as a double is something slightly less than 0.15. Check this out

DecimalFormat df = new DecimalFormat("#.#");

df.setRoundingMode(RoundingMode.HALF_UP);

BigDecimal bd = new BigDecimal(0.15);
System.out.println("bd=" + bd);
System.out.println(df.format(0.15)); // expecting 0.1, getting 0.1
bd = new BigDecimal(0.05);
System.out.println("bd=" + bd);
System.out.println(df.format(0.05));
bd = new BigDecimal(0.06);
System.out.println("bd=" + bd);
System.out.println(df.format(0.06));

The output of this code is

bd=0.1499999999999999944488848768742172978818416595458984375
0.1
bd=0.05000000000000000277555756156289135105907917022705078125
0.1
bd=0.059999999999999997779553950749686919152736663818359375
0.1

A possible solution (if you absolutely need it to round the right way) is to use BigDecimal.valueOf to create the value. For example

BigDecimal bd = BigDecimal.valueOf(0.15);
System.out.println("bd=" + bd);
System.out.println(df.format(bd)); // expecting 0.1, getting 0.1
bd = BigDecimal.valueOf(0.05);
System.out.println("bd=" + bd);
System.out.println(df.format(bd));
bd = BigDecimal.valueOf(0.06);
System.out.println("bd=" + bd);
System.out.println(df.format(bd));

Will now yield

bd=0.15
0.2
bd=0.05
0.1
bd=0.06
0.1

BTW, as Scary Wombat pointed out, the mask set as 0.0 instead of #.# will make 0.6 0. But I think that was a later edit then when I started looking at it. Use #.#.

like image 162
tofutim Avatar answered Aug 29 '26 15:08

tofutim



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!