patch ping Re: [java] Fix BigDecimal ROUND_HALF_EVEN
Per Bothner
per@bothner.com
Sat Jul 19 22:21:00 GMT 2003
Mark Wielaard wrote:
> You need half also to see if ROUND_UNNECESSARY can be satisfied.
I don't understand this.
> So the code becomes a bit messy with first two if statements for
> ROUND_CEILING and ROUND_FLOOR and then a big else block with the half
> calculation and a big switch, but I think it is still clear what the
> code does.
Ok.
> Another optimization can be done by noticing that with the new code we
> can just look at the remainder and be done when it is zero. That also
> makes that the ROUND_UNNECESSARY case can be pulled out of the big
> switch before even the sign is calculated.
Yes, that was my intent.
>>This (in the original code) looks questionable:
>> int sign = unrounded.signum ();
>>Consider the test in ROUND_CEILING:
>> roundingMode = (sign == 1) ? ROUND_UP : ROUND_DOWN;
>>Shouldn't this be whether the this.signum() is positive?
>>Consider dividing -9 by 10. unrounded.signum () is 0,
>>so we round down when we should be rounding up.
>
> In the above case unrounded.signum () would be -1.
> I believe the original is correct.
Ok, consider -9 divided by 100 instead (with all scales zero).
>>Have you tested it?
>
> There already were some 600 BigDecimal tests for Mauve. I added a couple
> more for some ROUND_HALF_EVEN corner cases (positive/negative, odd/even,
> different nearest neigbors or equidistant). All these tests pass with
> the patch below.
Do you test negative values of val as well?
> OK to commit?
Yes, but may I suggest some minor optimizations?
Instead of sign == -1 or sign == 1 it is probably more efficient to do
sign < 0 or sign > 0.
> if (roundingMode == ROUND_UP)
> - return new BigDecimal (unrounded.add (BigInteger.valueOf (1)), newScale);
> + return new BigDecimal (unrounded.add (BigInteger.valueOf
> + (sign != 0 ? sign : 1)), newScale);
>
> // roundingMode == ROUND_DOWN
> return new BigDecimal (unrounded, newScale);
if (roundingMode == ROUND_UP)
{
unrounded = unrounded.add(sign >= 0 ? BigInteger.ONE :
BigInteger.valueOf(-1));
}
return new BigDecimal (unrounded, newScale);
Calling new BigDecimal only once reduce code space.
The change to the operand to add is more arguable.
--
--Per Bothner
per@bothner.com http://per.bothner.com/
More information about the Java
mailing list