mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-01-19 03:14:04 +08:00
BigDecimal (divide): Correctly handle ROUND_HALF_EVEN when amount is greater than 0.5.
2003-08-01 Jerry Quinn <jlquinn@optonline.net> Mark Wielaard <mark@klomp.org> * java/math/BigDecimal (divide): Correctly handle ROUND_HALF_EVEN when amount is greater than 0.5. Simplify and optimize code. Co-Authored-By: Mark Wielaard <mark@klomp.org> From-SVN: r70049
This commit is contained in:
parent
cbd63935d8
commit
2f18d7a1a8
@ -1,3 +1,10 @@
|
||||
2003-08-01 Jerry Quinn <jlquinn@optonline.net>
|
||||
Mark Wielaard <mark@klomp.org>
|
||||
|
||||
* java/math/BigDecimal (divide): Correctly handle
|
||||
ROUND_HALF_EVEN when amount is greater than 0.5.
|
||||
Simplify and optimize code.
|
||||
|
||||
2003-07-31 Tom Tromey <tromey@redhat.com>
|
||||
|
||||
More for PR libgcj/11737:
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* java.math.BigDecimal -- Arbitrary precision decimals.
|
||||
Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
Copyright (C) 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
@ -273,7 +273,7 @@ public class BigDecimal extends Number implements Comparable
|
||||
// Ensure that pow gets a non-negative value.
|
||||
int valScale = val.scale;
|
||||
BigInteger valIntVal = val.intVal;
|
||||
int power = newScale + 1 - (scale - val.scale);
|
||||
int power = newScale - (scale - val.scale);
|
||||
if (power < 0)
|
||||
{
|
||||
// Effectively increase the scale of val to avoid an
|
||||
@ -285,50 +285,53 @@ public class BigDecimal extends Number implements Comparable
|
||||
BigInteger dividend = intVal.multiply (BigInteger.valueOf (10).pow (power));
|
||||
|
||||
BigInteger parts[] = dividend.divideAndRemainder (valIntVal);
|
||||
// System.out.println("int: " + parts[0]);
|
||||
// System.out.println("rem: " + parts[1]);
|
||||
|
||||
int roundDigit = parts[0].mod (BigInteger.valueOf (10)).intValue ();
|
||||
BigInteger unrounded = parts[0].divide (BigInteger.valueOf (10));
|
||||
|
||||
if (roundDigit == 0 && parts[1].signum () == 0) // no rounding necessary
|
||||
BigInteger unrounded = parts[0];
|
||||
if (parts[1].signum () == 0) // no remainder, no rounding necessary
|
||||
return new BigDecimal (unrounded, newScale);
|
||||
|
||||
int sign = unrounded.signum ();
|
||||
if (roundingMode == ROUND_UNNECESSARY)
|
||||
throw new ArithmeticException ("newScale is not large enough");
|
||||
|
||||
switch (roundingMode)
|
||||
int sign = intVal.signum () * valIntVal.signum ();
|
||||
|
||||
if (roundingMode == ROUND_CEILING)
|
||||
roundingMode = (sign > 0) ? ROUND_UP : ROUND_DOWN;
|
||||
else if (roundingMode == ROUND_FLOOR)
|
||||
roundingMode = (sign < 0) ? ROUND_UP : ROUND_DOWN;
|
||||
else
|
||||
{
|
||||
case ROUND_UNNECESSARY:
|
||||
throw new ArithmeticException ("newScale is not large enough");
|
||||
case ROUND_CEILING:
|
||||
roundingMode = (sign == 1) ? ROUND_UP : ROUND_DOWN;
|
||||
break;
|
||||
case ROUND_FLOOR:
|
||||
roundingMode = (sign == 1) ? ROUND_DOWN : ROUND_UP;
|
||||
break;
|
||||
case ROUND_HALF_UP:
|
||||
roundingMode = (roundDigit >= 5) ? ROUND_UP : ROUND_DOWN;
|
||||
break;
|
||||
case ROUND_HALF_DOWN:
|
||||
roundingMode = (roundDigit > 5) ? ROUND_UP : ROUND_DOWN;
|
||||
break;
|
||||
case ROUND_HALF_EVEN:
|
||||
if (roundDigit < 5)
|
||||
roundingMode = ROUND_DOWN;
|
||||
else
|
||||
// half is -1 if remainder*2 < positive intValue (*power), 0 if equal,
|
||||
// 1 if >. This implies that the remainder to round is less than,
|
||||
// equal to, or greater than half way to the next digit.
|
||||
BigInteger posRemainder
|
||||
= parts[1].signum () < 0 ? parts[1].negate() : parts[1];
|
||||
valIntVal = valIntVal.signum () < 0 ? valIntVal.negate () : valIntVal;
|
||||
int half = posRemainder.shiftLeft(1).compareTo(valIntVal);
|
||||
|
||||
switch(roundingMode)
|
||||
{
|
||||
int rightmost =
|
||||
unrounded.mod (BigInteger.valueOf (10)).intValue ();
|
||||
if (rightmost % 2 == 1) // odd, then ROUND_HALF_UP
|
||||
case ROUND_HALF_UP:
|
||||
roundingMode = (half < 0) ? ROUND_DOWN : ROUND_UP;
|
||||
break;
|
||||
case ROUND_HALF_DOWN:
|
||||
roundingMode = (half > 0) ? ROUND_UP : ROUND_DOWN;
|
||||
break;
|
||||
case ROUND_HALF_EVEN:
|
||||
if (half < 0)
|
||||
roundingMode = ROUND_DOWN;
|
||||
else if (half > 0)
|
||||
roundingMode = ROUND_UP;
|
||||
else // even, then ROUND_HALF_DOWN
|
||||
roundingMode = (roundDigit > 5) ? ROUND_UP : ROUND_DOWN;
|
||||
else if (unrounded.testBit(0)) // odd, then ROUND_HALF_UP
|
||||
roundingMode = ROUND_UP;
|
||||
else // even, ROUND_HALF_DOWN
|
||||
roundingMode = ROUND_DOWN;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (roundingMode == ROUND_UP)
|
||||
return new BigDecimal (unrounded.add (BigInteger.valueOf (1)), newScale);
|
||||
unrounded = unrounded.add (BigInteger.valueOf (sign > 0 ? 1 : -1));
|
||||
|
||||
// roundingMode == ROUND_DOWN
|
||||
return new BigDecimal (unrounded, newScale);
|
||||
|
Loading…
Reference in New Issue
Block a user