Java BigDecimal: are they equal?

How can you compar two numbers in Java?
Well, it is quite simple, there is the == operator! That’s true for simple types, not for objects, where the .equals method exists.
Since BigDecimals are objects, how do you test if two objects contain the same value? Not using .equals!
That’s true!
Consider the following piece of code:

BigDecimal a = new BigDecimal( "2.0" );
BigDecimal b = new BigDecimal( "2.00" );

if ( a.equals( b ) )
    System.out.println( "a equals b = " + a );

if ( a.compareTo( b ) == 0 )
    System.out.println( "a == b = " + a );


The first if branch evaluates to false, while the second evaluates to true.
Why?
The answer is in the documentation for the equals method:

Unlike compareTo, this method considers two BigDecimal objects equal only if they are equal in value and scale


It could have a sense in some universe, it does not make any sense to me because 2 is equal to 2.0, that is equal to 2.00 and so one, without any regard of the scale.
And just to take another look at the problem, how does Raku handle this? It gets the expected results:

% raku
To exit type 'exit' or '^D'
> 2 ~~ 2.0
True
> 2 ~~ 2.00
True
> 123456789.00000001 ~~ 123456789.000000010000000000
True



Therefore, the solution to compare two BigDecimals in Java is to use the compareTo method, even if you think the objects contain the same value.

Zero is not always Zero!

It can get even worst than the preceeding: how to compare zero? Again, consider the following piece of code:

BigDecimal a = new BigDecimal( "0.0" );
BigDecimal b = new BigDecimal( "0.00" );

// not working
if ( a.equals( b ) )
    System.out.println( "a equals b = " + a );

// working
if ( a.compareTo( b ) == 0 )
    System.out.println( "a == b = " + a );

// not working
if ( BigDecimal.ZERO.equals( a ) )
    System.out.println( "It is zero.zero!" );

// not working
if ( BigDecimal.ZERO.equals( b ) )
    System.out.println( "It is zero.zerozero!" );


And again, the BigDecimal.ZERO constant value cannot be easily compared to other values via the equals method!

Conclusions

Seems to me Java is pretty much confused about number precision.
While the test have been run against Java 11, I know this problem affects earlier (and probably later) versions. The fact is, from time to time, I forgot the semantic behind the usage of BigDecimal and stupidly try to equal-ize them.
Oh poor me!

The article Java BigDecimal: are they equal? has been posted by Luca Ferrari on October 28, 2021