JDK-8260692 : Mathematically wrong implementations of RoundingMode.HALF_UP and .HALF_DOWN
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.math
  • Affected Version: 8,11,17
  • Priority: P4
  • Status: Closed
  • Resolution: Won't Fix
  • Submitted: 2021-01-29
  • Updated: 2021-05-25
  • Resolved: 2021-02-01
Related Reports
Relates :  
Description
ADDITIONAL SYSTEM INFORMATION :
any system - since this was intended, however it is not correct

A DESCRIPTION OF THE PROBLEM :
HALF_UP should mean that a half-point number needs to be rounded towards the bigger number
1.5 rounded HALF_UP = 2 (this is implemented OK)
-1.5 rounded HALF_UP should be rounded to the bigger value, that is -1
=> implementation o HALF_UP for negative numbers is wrong
similarly,
HALF_DOWN should mean that a half-point number needs to be rounded towards the smaller number
1.5 rounded HALF_DOWN = 1 (this is implemented OK)
-1.5 rounded HALF_DOWN should be rounded to the smaller value, that is -2
=> implementation o HALF_DOWN for negative numbers is wrong

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
any usage of the HALF_UP or HALF_DOWN is not working mathematically correct
even the javadocs describe the desired behavior incorrectly => incorrect design

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
-1.5 rounded HALF_UP is: -1
-1.5 rounded HALF_DOWN is:-2
ACTUAL -
-1.5 rounded HALF_UP is: -2
-1.5 rounded HALF_DOWN is:-1

---------- BEGIN SOURCE ----------
NumberFormat nf = NumberFormat.getInstance();
nf.setMaximumFractionDigits(0);
nf.setMinimumFractionDigits(0);

nf.setRoundingMode(RoundingMode.HALF_UP);
System.out.println("-1.5 rounded HALF_UP is: " + nf.format(-1.5));
nf.setRoundingMode(RoundingMode.HALF_DOWN);
System.out.println("-1.5 rounded HALF_DOWN is:" + nf.format(-1.5));
---------- END SOURCE ----------

FREQUENCY : always



Comments
The specs and self-consistent and defined and desired. The RoundingMode.UP rounding mode uses "up" to mean "larger in magnitude", i.e. "away from zero". RoundingMode.HALF_UP means round UP, in the previous sense, in half way cases. This is how the mode is specified. There are already three variants of half-way rounding supported. Neither the designers of rounding modes for BigDecimal nor the subsequent designers of rounding mode support for decimal arithmetic in the IEEE 754 floating-point standard have found it necessary to support the addition half-way rounding policies advocated here. Closing as not a bug.
01-02-2021

UP is defined as "away from zero" (larger magnitude), and HALF_UP is consistent with that. There is also CEILING which means towards positive infinity. But I don't see a "HALF_CEILING" or anything equivalent, which seems to be what the submitter is asking for. (But it's also not clear to me whether this is useful.) A closer read of the specs is necessary to determine what, if anything, to do about this.
01-02-2021

The observations on Windows 10: JDK 8: Failed, -1.5 rounded HALF_UP is: -2 and -1.5 rounded HALF_DOWN is:-1 JDK 11: Failed. JDK 17ea build 6: Failed.
31-01-2021