So I recently started loving the language kotlin. Today, while comparing doubles, I came across the inevitable NaN
.
fun main(args: Array<String>) {
val nan = Double.NaN
println("1: " + (nan == nan))
println("2: " + (nan == (nan as Number)))
println("3: " + ((nan as Number) == nan))
}
N.B: (Double
is a subtype of Number
)
Running the above code yields:
1: false
2: true
3: true
I understand that comparing with NaN
in Java returns false
, so I would expect false
for all expressions.
How can this behavior be explained? What is the rationale behind it?
Use the IsNaN method to determine whether a value is not a number. The Equality operator considers two NaN values to be unequal to one another. In general, Double operators cannot be used to compare Double. NaN with other Double values, although comparison methods (such as Equals and CompareTo) can.
A constant holding the "not a number" value of Double.
In Kotlin, == is the default way to compare two objects: it compares their values by calling equals under the hood. Thus, if equals is overridden in your class, you can safely compare its instances using ==. For reference comparison, you can use the === operator, which works exactly the same as == in Java.
Referential equality ('===') === operator is used to compare the reference of two variable or object. It will only be true if both the objects or variables pointing to the same object. The negated counterpart of === in Kotlin is !== which is used to compare if both the values are not equal to each other.
That's because (2) and (3) are compiled to boxing a primitive and then Double.equals
check: on JVM, primitive double
can't be compared to a boxed one.
Double.equals
, in turn, checks equality by comparing doubleToLongBits(...)
of the two Double
s, and for the latter there's a guarantee that
If the argument is NaN, the result is
0x7ff8000000000000L
.
So, the bits returned for two NaN
are equal, and the rule NaN != NaN
is ignored here.
Also, as @miensol mentioned, there's another consequence of this equality check: +0
and -0
are equal according to ==
check and not to equals
check.
Equivalent code in Java would be:
double nan = Double.NaN;
System.out.println("1: " + (nan == nan)) //false
System.out.println("2: " + ((Double) nan).equals(((Number) nan)))
System.out.println("3: " + ((Number) nan).equals(nan));
The last two lines call Double.equals
, comparing doubleToLongBits(...)
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With