Search code examples
pythonsympysimplify

how to get SymPy to replace ints like 1.0 with 1


Sorry for the newbie question but I have not found the answer elsewhere so far.

Say we have a symbol and we multiply it by the float number one:

import sympy

x = sympy.Symbol('x')
x = 1.0 * x

All the expressions that contain this x will also contain factor one whatever I do:

from pprint import pprint
pprint(x)
pprint(sympy.simplify(x))

Output:

1.0⋅x
1.0⋅x

In the example above, I want to output x instead of 1.0⋅x. Is it possible to simplify the expression in the way that it solves all multiplications by a float number one? Should I transform this float number to another datatype?


Solution

  • Looks like it's due to the floating-point vs integer 1 - don't use 1.0 if you can get away with 1, perhaps?

    You could check if it's identically 1.0 with if f.as_integer_ratio() == (1, 1), and if so don't prepend the unnecessary '1.0':

    >>> xf = 1.0 * x
    >>> xi = 1 * x
    
    >>> xf
    1.0*x
    >>> xi
    x
    
    >>> pprint(xf)
    1.0*x
    >>> pprint(xi)
    x
    

    It might be due to floating-point inexactness (I don't know sympy much, can't say more).

    EDIT: the runtime of float.as_integer_ratio() is tiny, in response to your question:

    >>> python -m timeit -n 1000000 '(1.0).as_integer_ratio() == (1,1)'
    1000000 loops, best of 5: 172 nsec per loop
    
    >>> python -m timeit -n 1000000 '(1.1).as_integer_ratio() == (1,1)'
    1000000 loops, best of 5: 327 nsec per loop
    
    >>> python -m timeit -n 1000000 '(1.01).as_integer_ratio() == (1,1)'
    1000000 loops, best of 5: 331 nsec per loop
    
    >>> python -m timeit -n 1000000 '(0.999999999999).as_integer_ratio() == (1,1)'
    1000000 loops, best of 5: 329 nsec per loop