BigDecimal comparison?


(BigDecimal(“0E-8”) == BigDecimal.ZERO) - false
(BigDecimal(“0E-8”).compareTo(BigDecimal.ZERO) == 0) - true
(BigDecimal(“0E-8”) == BigDecimal.ZERO.setScale(8)) - true

Is it a bug?

New operators

The BigDecimal comparison functions are part of the JDK. Even if this behavior is a bug, it’s not a bug in Kotlin; you’ll see exactly the same with plain Java code.


Ah, so ==, <, > compares object references for BigDecimals in Kotlin?
But in this case (BigDecimal(“0E-8”) == BigDecimal.ZERO.setScale(8)) - should be false always not?


No. The == operator is compiled into a call of BigDecimal.equals(), and < and > are compiled into calls of BigDecimal.compareTo(), like for any other object. Both BigDecimal.equals() and BigDecimal.compareTo() are implemented in the JDK, and if you see any inconsistency, that’s a problem with the JDK implementation.


Consequence of this is that you get the following:

val zero = BigDecimal(“0E-8”)

(zero < BigDecimal.ZERO) // false
(zero > BigDecimal.ZERO) // false
(zero == BigDecimal.ZERO) // false


For BigDecimals equals checks both value and scale. d1.compareTo(d2) == 0 produces correct result and probably would be more meaningful for == operator.


I would think if an object implements Comparable, == should rather use compareTo. Expectation would be that < and > have the same semantics as ==

Both Scala and Groovy gives true for BigDecimal(“0E-8”) == BigDecimal.ZERO so looks like they do it this way…


FWIW, over the years there have been major user complaints arguing that Groovy should translate == to equals even for Comparable types (e.g.


Equals may be faster (see: String), compareTo isn’t tuned for equality testing.


IMO == operator should be configurable. For most cases equals is fine, but there are classes where equals just doesn’t make sense as ==: BigDecimal, Array. There should be a way to alter default behaviour and call compareTo() for BigDecimals, for Arrays, etc.


I’m not sure how you envision this configurability, especially in the presence of generic classes. It would be really weird to have == work differently for t: T in Foo<T> where T is BigDecimal and for t: BigDecimal.


I agree, it would be strange. Probably no good solution for that. May be it’s worth to implement BigDecimal wrapper to overcome this problem, like Scala did,


I solve that problem using infix

infix fun BigDecimal.equalsTo(other: BigDecimal) = this.compareTo(other)==0

if(result equalsTo BigDecimal.ZERO){


On the other hand, consider adding something like the spaceship operator that checks compareTo. But the syntax would be really strange, and I can see lexer problems coming (isn’t template<X<Y>> in C++ and x: T<U>=m in kotlin already bad enough?)