# [Python-Dev] Signalling NANs

Steven D'Aprano steve at pearwood.info
Fri Nov 9 06:05:07 EST 2018

```I'm trying to understand some unexpected behaviour with float NANs in
Python 3.5.

Background: in IEEE-754 maths, NANs (Not A Number) come in two flavours,
so called "quiet NANs" and "signalling NANs". By default, arithmetic
operations on qnans return a qnan; operations on snans "signal", which
in Python terms means raising an exception.

The original IEEE-754 standard didn't specify how to distinguish a qnan
from a snan, but a de facto standard arose that bit 51 of the float was
the "quiet bit", if it were set, the NAN was quiet.

For the purposes of this email, I'm going to assume that standard is in
place, even though technically speaking it is platform-dependent.

According to my tests, it seems that we cannot create snans in Python.
The float constructor doesn't recognise "snan", raising ValueError. Nor
can we convert a Decimal snan into a float:

py> from decimal import Decimal
py> snan = Decimal('snan')
py> float(dsnan)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: cannot convert signaling NaN to float

But unexpectedly (to me at least), we apparently cannot even create a
signalling NAN by casting 64 bits to a float. Here are the functions I
use to do the cast:

from struct import pack, unpack

def cast_float2int(x):
return unpack('<Q', pack('<d', x))[0]

def cast_int2float(i):
return unpack('<d', pack('<Q', i))[0]

Here's a regular quiet NAN round-tripping, as expected:

py> x = cast_int2float(0x7ff8000000000001)
py> x
nan
py> hex(cast_float2int(x))
'0x7ff8000000000001'

So far so good. But now let me try with a signalling NAN:

py> x = cast_int2float(0x7ff0000000000001)
py> x
nan
py> hex(cast_float2int(x))
'0x7ff8000000000001'

So it seems that the "quiet" bit is automatically set, even when using
the struct module, making it impossible to create snan floats.

Is this intended? If so, why?

Is this meant as a language feature?