I have a need to compare two DoubleArrays in order to determine if they have the same values in the same order. To do so I have used the contentEquals
extension function, however, it treats 0 and -0 as two different values (comparing them with ==
treats them the same).
For example:
val x = doubleArrayOf(1.0,0.0,-0.0)
val y = doubleArrayOf(1.0,0.0, 0.0)
x[0] == y[0] // true
x[1] == y[1] // true
x[2] == y[2] // true
x contentEquals y // false
Defining an extension function to do pairwise comparison myself,
infix fun DoubleArray.reallyEqual(other:DoubleArray) = (this.size == other.size) && this.zip(other).all {it.first == it.second}
x reallyEqual y // true
produces the expected result.
I am not sure if this is a bug, or if this is really the intended result, but it is a surprise as the individual equal tests compare true.
Looking at the source code, we can understand why this is this way. The contentEquals function delegates to java.util.Arrays::equals
/** * Returns `true` if the two specified arrays are *structurally* equal to one another, * i.e. contain the same number of the same elements in the same order. */ @SinceKotlin("1.1") @kotlin.internal.InlineOnly public inline infix fun DoubleArray.contentEquals(other: DoubleArray): Boolean { return java.util.Arrays.equals(this, other) }
and that method delegates to Double::equals
which considers these to be different
Two doubles d1 and d2 are considered equal if:
new Double(d1).equals(new Double(d2))
(Unlike the == operator, this method considers NaN equals to itself, and 0.0d unequal to -0.0d.)
Is this the intended behavior, or is the behavior that I am expecting the intended? I am not sure where bugs/feature requests for Kotlin are supposed to be reported, and this may belong there. If this is the intended behavior, perhaps a second method which delegates to ==
instead of Double::equals
should be included in the standard library. At very least, a note in the documentation that this method relies on Double::equals
instead of ==
and that the behavior is different.
Disclaimer: I am aware of the risks with precision when comparing double values with equality. Eventually, I will try to refactor my code so it doesn't rely on equality, but for now, it works with equality tests. This isn't a question about how to compare two arrays of doubles in general.