By the way, it's not as easy as you might think to test whether a value 
is a NAN or not.

There are currently three ways to test whether a value is a NAN. (Four 
if you include cmath.isnan.)

1. math.isnan(x) but it can fail in annoying ways.


    # No int is a NAN so this should return False
    py> math.isnan(10**1000)  
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    OverflowError: int too large to convert to float

    # Decimal signalling NANs are NANs so this should return True
    py> x = Decimal('snan')
    py> math.isnan(x)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    ValueError: cannot convert signaling NaN to float


2. Decimal.is_nan() but it only works with decimals. However it does 
work with signalling NANs.


3. Back before math.isnan existed, the idiomatic way to check for NANs 
was to test whether they were equal to themselves. Assuming that x is a 
kind of numeric type, we should expect that `x == x` except for NANs. 
But this too fails for signalling NANs:


    # Using the default Decimal context
    py> x == x
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    decimal.InvalidOperation: [<class 'decimal.InvalidOperation'>]


So there is no good way to check for an arbitrary NAN that duck-types 
floats, Decimals, ints, Fractions and other numeric types.

I have come up with this:


    def isnan(x, _isnan=math.isnan):
        try:
            return _isnan(x)
        except ValueError:
            # Could be a Decimal signalling NAN.
            try:
                return x.is_nan()
            except AttributeError:
                return x != x
        except OverflowError:
            return False
        except TypeError:
            from cmath import isnan
            return isnan(x)


but I fear that there could be other landmines waiting, other odd corner 
cases I haven't thought of.

See also 

https://bugs.python.org/issue27975



-- 
Steven
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/VHC4GO37ZT2UEW6RSRF4ASMTVK52UQ6H/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to