Thursday, September 12, 2019

Welcome to the float zone...

Consider a REPL with two tuples, a and b.

>>> type(a), type(b)
(<type 'tuple'>, <type 'tuple'>)
>>> a == b
True


So far, so good.  But let's dig deeper...

>>> a[0] == b[0]
False


The tuples are equal, but their contents is not.



>>> a is b
True





In fact, there was only ever one tuple.
What is this madness?

>>> a
(nan,)


Welcome to the float zone.

Many parts of python assume that a is b implies a == b, but floats break this assumption.  They also break the assumption that hash(a) == hash(b) implies a == b.

>>> hash(float('nan')) == hash(float('nan'))
True


Dicts handle this pretty elegantly:

>>> n = float('nan')
>>> {n: 1}[n]
1


>>> a = {float('nan'): 1, float('nan'): 2}
>>> a
{nan: 1, nan: 2}