[Python-Dev] Rich comparisons

Tim Peters tim.one at comcast.net
Tue Mar 30 00:00:20 EST 2004


[Edward Loper]
>> This means that 'nan' is no longer a well-behaved dictionary key:
>>
>>      >>> x = {float('nan'):0}
>>      >>> x[float('nan')] = 1
>>      >>> print x
>>      {nan: 0, nan: 1}

Whatever happened there is a platform accident.  For example, not even the
float('nan') part is portable.  On Python 2.3 on Windows, your example
already works that way (here just changed to spell NaN in a way that works
on Windows):

>>> inf = 1e3000
>>> x = {}
>>> x[inf - inf] = 0
>>> x[inf - inf] = 1
>>> print x
{-1.#IND: 0, -1.#IND: 1}
>>>

>> Even worse, we get different behavior if we use the "same copy" of
>> nan:
>>
>>      >>> nan = float('nan')
>>      >>> x = {nan:0}
>>      >>> x[nan] = 1
>>      >>> print x
>>      {nan: 1}

dict lookup does assume that "key1 is key2" implies "key1 == key2", so at
least that one will work the same way across platforms.

[Michael Hudson]
> Gah.  Still, I think this is more a theoretical objection than
> anything else?

I do.

> BTW, with 2.3 on OS X:
>
> >>> {1e3000/1e3000:1}[0]
> 1
> >>> {0:2}[1e3000/1e3000]
> 2
>
> So your 'no longer' isn't really valid :-)

>> If we *really* want nan==nan to be false, then it seems like we have
>> to say that nan is unhashable.

Python doesn't have access to a portable way (at the C level) to determine
whether something *is* a NaN, and the hash value of a NaN follows from
whatever accidental bits the platform C modf(NaN, &intpart) returns.

>> I'm also disturbed by the fact that cmp() has something different to
>> say about their equality:
>>
>>      >>> cmp(float('nan'), float('nan'))
>>      0

> Well, yah.  cmp() assumes a total ordering.  If there just isn't one,
> what can we do?

If we could recognize it was a NaN, my preference would be to raise an
exception.  I was told that GNU sort arranges to make NaNs look "less than"
all non-NaN floats, which is a way to make a total ordering -- kinda.  Not
all NaNs contain the same bits, and depending on other platform accidents
"the other bits" in a NaN may or may not have significance to the platform C
and its libraries.

> I have at no point claimed that I have given Python 2.4 a coherent
> ieee 754 floating point story.

Ya, but I keep telling people you claim that <wink>.

> All I have tried to do is /reduce/ the level of surprise knocking
> around, and I think I've succeeded.

Making

    x relop y

return the same thing as the platform C does reduce the surprise -- at least
for those who aren't surprised by their platform C's behavior.

> If someone (not me!) has the time and energy to do a 'proper job' (and
> I'd expect working out what that means to be the hard part), then you
> have my support and pre-emptive thanks.

I don't believe it will happen until all the major C compilers support the
(still optional!) 754 gimmicks in C99 -- or Python is rewritten in some
other language that supports them.  Before then, we'd need a small army of
people expert in the intersection of their platform C and the 754 standard,
to produce piles of #ifdef'ed platform-specific implementation code.  That's
doable, but unlikely.

tomorrow-is-usually-like-yesterday-ly y'rs  - tim




More information about the Python-Dev mailing list