Search code examples
pythonfloating-pointintegersympy

Sympy check if a number is natural


If I some random number, how do I check if it's an integer (∈ ℕ)?

>>> from sympy.core.numbers import Float
>>> Float(2)
2.00000000000000
>>> Float(2).is_integer
False # what ??

I've found a simple workaround but I feel It's some kind of a hack:

>>> Float(2) % 1 == 0
True
>>> Float(2.5) % 1 == 0
False

So is there a more proper way of finding if a number is natural ?


Solution

  • This sort of query arises throughout the SymPy codebase and the solution that we have for this is to use as_int on the expression in question. When the strict flag is off, a float that is equivalent to the int will be returned as an int. Otherwise (or if the expression is not an integer) a ValueError will be raised:

    >>> from sympy import Float
    >>> from sympy.core.compatibility import as_int
    >>> as_int(2.0)
    Traceback (most recent call last):
    ... 
    ValueError: 2.0 is not an integer
    
    >>> as_int(2.0, strict=False)
    2
    

    Using this in a test function gives:

    >>> def isint(i):
    ...     try: as_int(i, strict=False)
    ...     except: return False
    ...     return True
    >>> isint(Float(2))
    True
    

    Another way to approach this is to check whether the decimal portion of a number is 0:

    >>> (Float(2)%1).is_zero
    True
    

    UPDATE: In version 1.12 as_int can be imported from sympy.utilities.misc. And in 1.13 the int_valued can be imported from sympy.core.numbers:

    >>> from sympy.core.number import int_valued
    >>> int_valued(0.5)
    False
    >>> int_valued(1.0)
    True