Behavior change in rounding in NumberFormat and DecimalFormat format methods

Java 8 introduces a behavior change in the rounding behavior of decimal numbers using the format method on the java.text.NumberFormat and the java.text.DecimalFormat classes when the value is very close to a tie, sitting exactly at the rounding position specified in the formatting pattern. The change affects numbers with a binary numeric representation that is not exact.

For example, the closest binary approximation of 0.015 that a computer can reach is 0.01499999999999999944488848768742172978818416595458984375. If you round down that number to two digits, in Java 8 the answer is .01 because .004999999.... is less than .005. In previous versions of Java, the answer is 0.02.

This rule flags calls to the NumberFormat and DecimalFormat format methods when they are called with a double primitive or a java.lang.Double object as the first parameter. The following example shows the use of the format methods.

public static void main(String[] args) {

java.text.NumberFormat nf = java.text.NumberFormat.getInstance();
nf.setMaximumFractionDigits(3);
double aDouble;
String myStr;

aDouble = 0.8055d;
myStr = nf.format(aDouble);
System.out.println("format(" + aDouble + ") returns \"" + myStr + "\". Expecting \"0.805\".");

nf.setMaximumFractionDigits(2);
aDouble = 0.015d;
myStr = nf.format(aDouble);
System.out.println("format(" + aDouble + ") returns \"" + myStr + "\". Expecting \"0.01\".");


NumberFormat percent = NumberFormat.getPercentInstance();
percent.setMinimumFractionDigits(1);
percent.setMaximumFractionDigits(1);
percent.setRoundingMode(RoundingMode.HALF_EVEN);
myStr = percent.format(0.5555);
System.out.println("format(0.5555) returns \"" + myStr + "\". Expecting \"55.5%\".");

}

If you call this code using Java 7, the following output is displayed:

format(0.8055) returns "0.806". Expecting "0.805".
format(0.015) returns "0.02". Expecting "0.01".
format(0.5555) returns "55.6%". Expecting "55.5%".

In Java 8, the following output is displayed:

format(0.8055) returns "0.805". Expecting "0.805".
format(0.015) returns "0.01". Expecting "0.01".
format(0.5555) returns "55.5%". Expecting "55.5%".

Be aware of this behavior change because it might affect your program output. The JDK-7131459 bug report provides more information and shows a number of related reports, including bug reports against Java 8 that report this as a regression.

For more information about the affected classes, see the following resources: