[Python-Dev] Why is nan != nan?

Mark Dickinson dickinsm at gmail.com
Thu Mar 25 15:54:55 CET 2010


On Thu, Mar 25, 2010 at 2:42 PM, Mark Dickinson <dickinsm at gmail.com> wrote:
> On Thu, Mar 25, 2010 at 2:26 PM, Antoine Pitrou <solipsis at pitrou.net> wrote:
>> This sounds a bit sophistic, if the (Python) user doesn't have access to
>> the payload anyway.
>
> Well, you can get at the payload using the struct module, if you care
> enough.  But yes, it's true that Python doesn't take much care with
> the payload:  e.g., ideally, an operation on a nan (3.0 + nan,
> sqrt(nan), ...) should return exactly the same nan, to make sure that
> information in the payload is preserved.  Python doesn't bother, for
> floats (though it does for decimal).

Hmm. I take it back.  I was being confused by the fact that sqrt(nan)
returns a nan with a new identity;  but it does apparently preserve
the payload.  An example:

>>> from struct import pack, unpack
>>> from math import sqrt
>>> x = unpack('<d', pack('<Q', (2047 << 52) + 12345))[0]
>>> y = sqrt(x)
>>> bin(unpack('<Q', pack('<d', x))[0])
'0b111111111110000000000000000000000000000000000000011000000111001'
>>> bin(unpack('<Q', pack('<d', y))[0])
'0b111111111111000000000000000000000000000000000000011000000111001'

Here you see that the payload has been preserved.  The bit patterns
aren't quite identical:  the incoming nan was actually a signaling
nan, which got silently (because neither Python nor C understands
signaling nans) 'silenced' by setting bit 51.  So the output is the
corresponding quiet nan, with the same sign and payload.

Mark


More information about the Python-Dev mailing list