You could use the ordered_float
crate to wrap around those floats to be hashed. If an explicit wrapper is undesirable, there is derivative
crate allowing you to customize the hash function of a field (remember to alter Eq
as well).
Fun fact: NaN is not the only issue. Java implemented hashCode()
wrongly making -0 and +0 produce different values, forcing Float.equals()
to have a very strange semantics. You will get the same problem if you implement the hash by bit-casting the f32 to u32 without checking for ±0.
| Language | ±0 | NaNs |
|----------------------|-----------|----------------|
| Java | Different | Same |
| Python | Same | Same |
| Ruby | Same | Different |
| Swift | Same | Different |
| C++ (libc++) | Same | Different |
| Rust (ordered_float) | Same | Same |