# Various equalities of NaN?

I know of three functions for checking for equality: `==`, `===`, and `isequal`. The documentation comments on subtlety regarding floating point numbers, and there is indeed a difference:

``````julia> NaN == NaN
false

julia> isequal(NaN, NaN)
true

julia> NaN === NaN
true
``````

Could you explain why they behave this way? I am particularly interested in

1. Why isequal was designed to behave differently from == for float numbers.
2. Why `NaN === NaN` is `true`. For most other types, I would have naively assumed `a === b` implies `a==b` since `x===y`
`````` Determine whether x and y are identical, in the sense that no program could distinguish them.
``````

according to the documentation.

In terms of my knowledge level, I know floating point numbers are represented as bitstrings with a sign bit, exponent bits, and mantissa bits, but don’t really know much else.

How NaN are handled is outlined in IEEE-754. All comparisons between NaN and any number including itself return false.

`===` on the other hand is a different operation that checks that no operation could tell them apart. For mutable structs this is pointer equality and for immutable structs this is bitwise equality.

There are actually several different representations for NaN’s, which are not `===`. The best way to check if a value is NaN is with the function `isnan`

5 Likes

Thanks for pointing me to IEEE-754. I’ve always thought of `==` as checking for equality of value, and did not know there was a specification given by IEEE. Now it makes sense that `NaN==NaN` is false but `Nan === Nan`.

Do you also happen to know why `isequal` was designed to return `true` for two `NaN` in Julia?

NaNs not being equal to each other can often be unhelpful behavior. For those cases `isequal` is simpler then having to explicitly handle NaN’s.

`===` isn’t much help for those cases as there can be multiple different bitwise representations of NaNs.

1 Like

As @WschW notes, there is only one best practice when it comes to determining if one or more values is “not a number” (NaN): use `isnan(x)` or, to determine if two values are NaNs, use e.g. `nans(x,y) = isnan(x) && isnan(y)` . And, fortunately, `isnan(x)` runs fast.

2 Likes

`isequal` is used in hashing, so it has to work like this. See

for a related discussion.

1 Like

For floats `isequal` is defined differently then `===`. you can see the definition for how the former handles floats is:

``````isequal(x::AbstractFloat, y::AbstractFloat) = (isnan(x) & isnan(y)) | signequal(x, y) & (x == y)
``````

This function returns true if both values are NaN’s.

This is distinct behaviour from `===` which in this case would return false if either the sign or any part of the mantissa differed.

1 Like

Ah that makes sense. Did not know `isequal` was the function used for hashing. Thanks!

Thank you all for clarifying the differences as well as why they exist!