JDK-8087313 : Rounding HALF_DOWN issue
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.math
  • Affected Version: 8,8u45,9
  • Priority: P3
  • Status: Resolved
  • Resolution: Not an Issue
  • OS: windows_7
  • CPU: x86_64
  • Submitted: 2015-06-11
  • Updated: 2015-06-19
  • Resolved: 2015-06-19
Related Reports
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.8.0_45"
Java(TM) SE Runtime Environment (build 1.8.0_45-b15)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.1.7601]

A DESCRIPTION OF THE PROBLEM :
If I am using rounding half down, and have a number that ends with 5(half), then the output of the formattor will be incorrect.
For example:
new DecimalFormat("#,##0.0000");
Double toFormat = 10.55555;
the output will be 10.5556, and I am expecting 10.5555.

REGRESSION.  Last worked in version 7u75

ADDITIONAL REGRESSION INFORMATION: 
java version "1.7.0_21"
Java(TM) SE Runtime Environment (build 1.7.0_21-b11)
Java HotSpot(TM) 64-Bit Server VM (build 23.21-b01, mixed mode)

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Create a DecimalFormat like this:
DecimalFormat format = new DecimalFormat("#,##0.0000");
Set rounding half down
format.setRoundingMode(RoundingMode.HALF_DOWN);
Give this number to format:
Double toFormat = 10.55555;
Call the method format(Object obj) on the formatter

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
10.5555
ACTUAL -
10.5556

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
package testjava8;

import java.math.RoundingMode;
import java.text.DecimalFormat;

/**
 * Created by cristian.nandrean on 6/11/2015.
 */
public class Formatori {

    public static void main(String[] args) {
        DecimalFormat format = new DecimalFormat("#,##0.0000");
        format.setRoundingMode(RoundingMode.HALF_DOWN);
        Double toFormat = 10.55555;
        System.out.println("Round down");
        System.out.println(format.format(toFormat));//working BAD (is a BUG)

        format.setRoundingMode(RoundingMode.HALF_UP);
        toFormat = 10.55555;
        System.out.println("Round up");
        System.out.println(format.format(toFormat));//working GOOD
    }
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
There isn't one.


Comments
Resolving as "Not an Issue" on the basis of the reasoning in the foregoing comment that the internal computer representation of the mathematical value 10.55555, which is the halfway point between the mathematical values 10.5555 and 10.5556, is actually greater than the mathematical value 10.55555, hence HALF_DOWN and HALF_UP both correctly round this value to 10.5556.
19-06-2015

In effect if we execute this code snippet BigDecimal bdd = new BigDecimal(10.55555); BigDecimal bds = new BigDecimal("10.55555"); System.out.println(bdd + "\n" + bds + "\n"); DecimalFormat format = new DecimalFormat("#,##0.0000"); format.setRoundingMode(RoundingMode.HALF_DOWN); System.out.println(format.format(bdd, new StringBuffer(), new FieldPosition(0))); System.out.println(format.format(bds, new StringBuffer(), new FieldPosition(0))); System.out.println(); format.setRoundingMode(RoundingMode.HALF_UP); System.out.println(format.format(bdd, new StringBuffer(), new FieldPosition(0))); System.out.println(format.format(bds, new StringBuffer(), new FieldPosition(0))); we obtain the output 10.555550000000000210320649784989655017852783203125 10.55555 10.5556 10.5555 10.5556 10.5556 which shows that the internal representation of the mathematical value 10.55555 is in fact slightly larger than 10.55555 so that HALF_DOWN and HALF_UP give the same result, 10.5556. When the BigDecimal is created from the String "10.55555" however the mathematically expected result is obtained.
17-06-2015

This is most likely another case of the correct, but surprising, behavior after the fix for JDK-7131459. See the release note commentary in http://www.oracle.com/technetwork/java/javase/8-compatibility-guide-2156366.html
15-06-2015

Ref: https://docs.oracle.com/javase/8/docs/api/java/math/RoundingMode.html ----------------------------------------------------------------------------------------------------------------------------------------------- 5.5 should be rounded to 5 with HALF_DOWN mode. In the test case, 10.55555 is rounded to 10.5556, though expected is 10.5555. 1. To reproduce, run the attached test case (Formatori.java). Checked this with JDK 7, 7u80, 8, 8u45, 8u60 ea b19, and 9 ea b68 with similar results. 2. Result: --------------- 7: OK 7u80: OK 8: FAIL 8u45: FAIL 8u60 ea b19: FAIL 9 ea b68: FAIL 3. Output from JDK 7u80: -------------------------------------- > java Formatori Round down 10.5555 Round up 10.5556 4. Output from JDK 8u45: --------------------------------------- > java Formatori Round down 10.5556 Round up 10.5556 5. This seems a regression in JDK 8 and 9.
12-06-2015