Failure cases:1) Positive
Float values rounded incorrectly: 99999992f to 99999997f
Double values rounded incorrectly: 0.99999999999999984 to 0.99999999999999994
Rounding modes: CEILING or UP
Expected: 1
Actual: 2
2) Negative
Float values rounded incorrectly: -99999992f to -99999997f
Double values rounded incorrectly: -0.99999999999999984 to -0.99999999999999994
Rounding modes: FLOOR or UP
Expected: -1
Actual: -2
Remarks:
The reason is that values between 0 and 1 have higher fraction precision than values between 1 and 2. The code adds 1.0 to the value x, and double arithmetic uses HALF_EVEN rounding by default. This leads to unexpected results for edge cases when HALF_EVEN triggers rounding UP to 2.
Proposed FIX:
The FIX is to cast the float/double value x to a int/long before the addition of 1.0:
Current: x + 1.0
Fixed: (long)x + 1.0
Bug occurs in code copied from Guava. An issue has been raised and a pull request submitted to the guava project:
Failure cases: 1) Positive Float values rounded incorrectly:
99999992f
to99999997f
Double values rounded incorrectly:0.99999999999999984
to0.99999999999999994
Rounding modes: CEILING or UP Expected: 1 Actual: 22) Negative Float values rounded incorrectly:
-99999992f
to-99999997f
Double values rounded incorrectly:-0.99999999999999984
to-0.99999999999999994
Rounding modes: FLOOR or UP Expected: -1 Actual: -2Remarks: The reason is that values between 0 and 1 have higher fraction precision than values between 1 and 2. The code adds 1.0 to the value x, and double arithmetic uses HALF_EVEN rounding by default. This leads to unexpected results for edge cases when HALF_EVEN triggers rounding UP to 2.
Proposed FIX: The FIX is to cast the float/double value x to a int/long before the addition of 1.0: Current:
x + 1.0
Fixed:(long)x + 1.0
Bug occurs in code copied from Guava. An issue has been raised and a pull request submitted to the guava project: