Search code examples
javaroundingieee-754bankers-rounding

Why does DecimalFormat round inconsistently?


import java.text.*;

public class TryStuffOut {
    public static void main(String[] args) {
       double n=12323233.445;
       DecimalFormat x = new DecimalFormat("#.##");
       System.out.println(x.format(n));
    }
}

why does this round the decimal part down to .44 and when i switch the variable n to double n=12323233.415; it rounds up to .42 . Why? and does the # in front of the deicmal matter to how many digits I have because it still seems to print out the entire number even thought I only have 1 pound sign.

Thanks


Solution

  • Explanation

    Due to limited floating point precision your double values are not actually what you wanted to have.

    In fact, the values are instead:

    12323233.445 -> 12323233.445000000298
    12323233.415 -> 12323233.4149999991059
    

    The rounding has to work with that, hence it rounds the first value up and the second value down.

    Note that your observation is incorrect and it is exactly the opposite. You claimed that the first would be rounded down while second value is rounded up. But executing it yields the opposite behavior. And that behavior is explained due to above.

    Floating point numbers are implemented according to IEE 754 and this specifies exactly how they work internally.


    Representation

    Now, the thing is that those numbers can not be represented. The specification says that it should then use the closest number that can be represented instead. And that is exactly what is happening here.

    You can inspect this further and play with it here: