Permalink
Browse files

Fix DoubleMath rounding bug identified in Guava issue 2509.

The approach is a little changed from the pull request #2511 -- more exhaustive testing, and it does more math in long arithmetic before casting back to a double.
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=126331169
  • Loading branch information...
lowasser authored and cpovirk committed Jun 30, 2016
1 parent 4768505 commit 1b1163b7e2c121d4a5b25b8966714201551976c4
@@ -106,7 +106,10 @@ public void testRoundFractionalDoubleToInt() {
& expected.compareTo(MIN_INT_AS_BIG_DECIMAL) >= 0;
try {
assertEquals(expected.intValue(), DoubleMath.roundToInt(d, mode));
assertEquals(
"Rounding " + d + " with mode " + mode,
expected.intValue(),
DoubleMath.roundToInt(d, mode));
assertTrue(isInBounds);
} catch (ArithmeticException e) {
assertFalse(isInBounds);
@@ -220,6 +220,16 @@ public BigInteger apply(BigInteger x) {
fractionalBuilder.add(d * scale).add(-d * scale);
}
}
for (int i = Double.MIN_EXPONENT; i <= Double.MAX_EXPONENT; i++) {
for (int direction : new int[] {1, -1}) {
double d =
Double.longBitsToDouble(Double.doubleToLongBits(Math.scalb(1.0, i)) + direction);
// Math.nextUp/nextDown
if (d != Math.rint(d)) {
fractionalBuilder.add(d);
}
}
}
for (double d : Doubles.asList(0, 1, 2, 7, 51, 102, Math.scalb(1.0, 53), Integer.MIN_VALUE,
Integer.MAX_VALUE, Long.MIN_VALUE, Long.MAX_VALUE)) {
for (double delta : Doubles.asList(0.0, 1.0, 2.0)) {
@@ -66,14 +66,14 @@ static double roundIntermediate(double x, RoundingMode mode) {
if (x >= 0.0 || isMathematicalInteger(x)) {
return x;
} else {
return x - 1.0;
return (long) x - 1;
}
case CEILING:
if (x <= 0.0 || isMathematicalInteger(x)) {
return x;
} else {
return x + 1.0;
return (long) x + 1;
}
case DOWN:
@@ -83,7 +83,7 @@ static double roundIntermediate(double x, RoundingMode mode) {
if (isMathematicalInteger(x)) {
return x;
} else {
return x + Math.copySign(1.0, x);
return (long) x + (x > 0 ? 1 : -1);
}
case HALF_EVEN:

0 comments on commit 1b1163b

Please sign in to comment.