diff --git a/jdk/src/share/classes/java/math/BigDecimal.java b/jdk/src/share/classes/java/math/BigDecimal.java index 0feec208bb9..4d76b4010e7 100644 --- a/jdk/src/share/classes/java/math/BigDecimal.java +++ b/jdk/src/share/classes/java/math/BigDecimal.java @@ -315,6 +315,10 @@ public class BigDecimal extends Number implements Comparable { new BigDecimal(BigInteger.ZERO, 0, 15, 1), }; + // Half of Long.MIN_VALUE & Long.MAX_VALUE. + private static final long HALF_LONG_MAX_VALUE = Long.MAX_VALUE / 2; + private static final long HALF_LONG_MIN_VALUE = Long.MIN_VALUE / 2; + // Constants /** * The value 0, with a scale of 0. @@ -1455,10 +1459,15 @@ public class BigDecimal extends Number implements Comparable { } else if (roundingMode == ROUND_FLOOR) { // Towards -infinity increment = (qsign < 0); } else { - if (isLongDivision || ldivisor != INFLATED) - cmpFracHalf = longCompareMagnitude(2 * r, ldivisor); - else + if (isLongDivision || ldivisor != INFLATED) { + if (r <= HALF_LONG_MIN_VALUE || r > HALF_LONG_MAX_VALUE) { + cmpFracHalf = 1; // 2 * r can't fit into long + } else { + cmpFracHalf = longCompareMagnitude(2 * r, ldivisor); + } + } else { cmpFracHalf = mr.compareHalf(mdivisor); + } if (cmpFracHalf < 0) increment = false; // We're closer to higher digit else if (cmpFracHalf > 0) // We're closer to lower digit diff --git a/jdk/test/java/math/BigDecimal/DivideTests.java b/jdk/test/java/math/BigDecimal/DivideTests.java index 89692255edc..7d04a60ca4b 100644 --- a/jdk/test/java/math/BigDecimal/DivideTests.java +++ b/jdk/test/java/math/BigDecimal/DivideTests.java @@ -23,7 +23,7 @@ /* * @test - * @bug 4851776 4907265 6177836 + * @bug 4851776 4907265 6177836 6876282 * @summary Some tests for the divide methods. * @author Joseph D. Darcy * @compile -source 1.5 DivideTests.java @@ -328,6 +328,35 @@ public class DivideTests { } } + // 6876282 + BigDecimal[][] testCases2 = { + // { dividend, divisor, expected quotient } + { new BigDecimal(3090), new BigDecimal(7), new BigDecimal(441) }, + { new BigDecimal("309000000000000000000000"), new BigDecimal("700000000000000000000"), + new BigDecimal(441) }, + { new BigDecimal("962.430000000000"), new BigDecimal("8346463.460000000000"), + new BigDecimal("0.000115309916") }, + { new BigDecimal("18446744073709551631"), new BigDecimal("4611686018427387909"), + new BigDecimal(4) }, + { new BigDecimal("18446744073709551630"), new BigDecimal("4611686018427387909"), + new BigDecimal(4) }, + { new BigDecimal("23058430092136939523"), new BigDecimal("4611686018427387905"), + new BigDecimal(5) }, + { new BigDecimal("-18446744073709551661"), new BigDecimal("-4611686018427387919"), + new BigDecimal(4) }, + { new BigDecimal("-18446744073709551660"), new BigDecimal("-4611686018427387919"), + new BigDecimal(4) }, + }; + + for (BigDecimal test[] : testCases2) { + BigDecimal quo = test[0].divide(test[1], RoundingMode.HALF_UP); + if (!quo.equals(test[2])) { + failures++; + System.err.println("Unexpected quotient from " + test[0] + " / " + test[1] + + " rounding mode HALF_UP" + + "; expected " + test[2] + " got " + quo); + } + } return failures; }