BigDecimal stripTrailingZeros and equality

82 Views Asked by At

Given

BigDecimal a = ...;
BigDecimal b = ...;

Do the following hold for all possible values of a and b?

if (a.compareTo(b) == 0)
    assert a.stripTrailingZeros().equals(b.stripTrailingZeros())
if (a.compareTo(b) != 0)
    assert !(a.stripTrailingZeros().equals(b.stripTrailingZeros()))

if (a.stripTrailingZeros().equals(b.stripTrailingZeros()))
    assert(a.compareTo(b) == 0)
if (!(a.stripTrailingZeros().equals(b.stripTrailingZeros())))
    assert(a.compareTo(b) != 0)

Or is there some edge case where the above assertions are not all true?

3

There are 3 best solutions below

0
Sweeper On BEST ANSWER

Note that stripTrailingZeros can throw an ArithmeticException if the resulting scale overflows. For example;

new BigDecimal(
        new BigInteger("70"),
        Integer.MIN_VALUE
).stripTrailingZeros(); // tries to set the scale to Integer.MIN_VALUE - 1 but can't

Other than such cases, the assertion should be true, because there is only one unique BigDecimal representation of each number, that has no trailing zeroes.

0
Lajos Arpad On

a.compareTo(b) is either 0 or something else. There is no third possibility where it is not 0 nor something else.

a.stripTrailingZeros().equals(b.stripTrailingZeros()) is either true or not true. There is no third possibility.

So, the answer is yes.

0
Kayaman On

BigDecimal.equals() says

Unlike compareTo, this method considers two BigDecimal objects equal only if they are equal in value and scale (thus 2.0 is not equal to 2.00 when compared by this method).

So while you might be able to get differing results with equals() using compareTo() won't be confused by the (possible) scale changes done with stripTrailingZeros():

For example, stripping the trailing zeros from the BigDecimal value 600.0, which has [BigInteger, scale] components equals to [6000, 1], yields 6E2 with [BigInteger, scale] components equals to [6, -2]. If this BigDecimal is numerically equal to zero, then BigDecimal.ZERO is returned.

Since BigDecimal also doesn't support NaN or infinities, there's no tricky edge cases like NaN != NaN that would cause issues (besides the standard risks of floating point usage).