JDK-6609637 : [Fmt-Nu] Rounding error of class java.text.DecimalFormat with #0.00 pattern
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.text
  • Affected Version: 1.4.2
  • Priority: P4
  • Status: Resolved
  • Resolution: Not an Issue
  • OS: windows_2000
  • CPU: x86
  • Submitted: 2007-09-26
  • Updated: 2014-11-17
  • Resolved: 2014-11-17
Related Reports
Relates :  
Description
FULL PRODUCT VERSION :
Under Windows2000Professional: java version "1.4.2_02"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_02-b03)
Java HotSpot(TM) Client VM (build 1.4.2_02-b03, mixed mode)

Under HP-UX: Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.1.10-030630-10:50)
Java HotSpot(TM) Server VM (build 1.3.1 1.3.1.10-_30_jun_2003_11_52 PA2.0, mixed mode)


ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows 2000 [Version 5.00.2195]   (checked bug with java.version=1.4.2_02)
HP-UX B.11.11 U 9000/800 1113474677 (checked bug with java.runtime.version=1.3.1.10-030630-10:50)

A DESCRIPTION OF THE PROBLEM :
The class java.text.DecimalFormat with #0.00 pattern fail rounding.
It fails when the centesimal number is par, is correct otherwise (odd).


STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Make instace of java.text.DecimalFormat("#0.00") and then try to round the double value 0.025 (or every other number with decimal number par, i.e 0.045 0.065 ...)


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
    n=0.024  : 0.02
    n=0.025  : 0.03 <== see here
    n=0.026  : 0.03
    ...
    ...
    n=0.034  : 0.03
    n=0.035  : 0.04
    n=0.036  : 0.04
    
ACTUAL -
    n=0.024  : 0.02
    n=0.025  : 0.02 <== MUST BE 0.3
    n=0.026  : 0.03
    ...
    ...
    n=0.034  : 0.03
    n=0.035  : 0.04 <== IS OK!
    n=0.036  : 0.04
    

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.text.DecimalFormat;

/**
 *
 * @author Daniele Belli <a href=mailto:###@###.###>Daniele Belli</a>
 * The pourpose of this class is to show a bug of DecimalFormat class.<br>
 * This tester class print a table of number from 0.000 to 0.999 and its rounded number to two decimal from 0.00 to 1.00<br>
 * using #0.00 format string.<br>
 *
 * The bug is in rounding (for example): <br>
    n=0.024  : 0.02 <br>
    n=0.025  : 0.02 <== MUST BE 0.3 <br>
    n=0.026  : 0.03 <br>
    ... <br>
    ... <br>
    n=0.034  : 0.03 <br>
    n=0.035  : 0.04 <== IS OK! <br>
    n=0.036  : 0.04 <br><br>
    
    Seems that with a decimal number odd the round of number hundredth is correct.<br>
    Instead of with a par decimal number the round fails.
    
 */

public class DecimalFormatTester {
    
    public DecimalFormatTester() {
        
        int multiplier = 1000;
        double n=0;
        
        DecimalFormat df=new DecimalFormat("#0.00");
        
        for (int i=1 ; i<multiplier ; i++) {
            
            n = i/ ((double) multiplier) ;
            System.out.println("n=" + n + "\t : " + df.format(n) );
        }

    }
    
    public static void main (String args[]) {
        System.getProperties().list(System.out);
        new DecimalFormatTester();
    }
}


---------- END SOURCE ----------

Comments
The expected results in the test are wrong: With a HALF_EVEN rounding as is the case here (default instanciation), rounding up happens only if digit at fractional rounding place (here the second) is odd (see RoundingMode javadoc) So Expected result for n= 0.025 is 0.02 ('2' is even), NOT 0.03, n= 0.035 is 0.04 ('3' is odd) Thus test is incorrect. Results for ANY JDK prior to 8 will however suffer from JDK-7131459 long-standing bug, with wrong results like: n = 0.015 will WRONGLY return 0.02 where it should return 0.01 because closest binary representation of 0.015 is "below the tie", i.e closest binary approximation that can be reached by a computer is 0.01499999999999999944488848768742172978818416595458984375. Starting JDK8, any JDK will provide the correct answer in all cases. Closing this one as "not a bug"
17-11-2014