Thursday, July 06, 2006

fmt:formatNumber rounding behavior

I was helping a coworker with a rounding "bug" earlier today. On one of our jspx pages, we need to round some numbers up. But she ran into a strange problem because 200.5 rounded to 200 but 21.5 rounded to 22. She thought the problem was hibernate related but a couple of quick unit tests revealed the real culprit: jstl's fmt:formatNumber tag. It's actually not a bug at all because according to the javadocs, it relies on the following for rounding:

ROUND_HALF_EVEN

public static final int ROUND_HALF_EVEN
Rounding mode to round towards the "nearest neighbor" unless both neighbors are equidistant, in which case, round towards the even neighbor. Behaves as for ROUND_HALF_UP if the digit to the left of the discarded fraction is odd; behaves as for ROUND_HALF_DOWN if it's even. Note that this is the rounding mode that minimizes cumulative error when applied repeatedly over a sequence of calculations.

Unfortunately, there's no way to change the behavior to ROUND_HALF_UP which is what we wanted. I'll send a note to the jstl mailing list to see if anyone else would like this feature and if so submit a patch.

*Update Before I sent that email to the mailing list, I did more digging and discovered that fmt:formatNumber is backed by DecimalFormat. As of Java 5, DecimalFormat does not support specifying a rounding mode other than the default ROUND_HALF_EVEN. The good news is that setRoundingMode was introduced in Java 6 to solve this exact problem. The bad news is that it'll be a while before java 6 is out of beta and this change gets propogated down to fmt:formatNumber. So in the meantime, the best thing to do is write your own tag is you require a rounding mode other than ROUND_HALF_EVEN.

3 comments:

objects said...
This comment has been removed by the author.
objects said...

Rounding strategy used by DecimalFormat

Anonymous said...

HIII help me in compsci i suck
- moooooooooo