Question

I have an expression from a sympy calculation:

sqrt(pi)*(0.333333333333333*a + 0.333333333333333*b - 2.66666666666667*c**2)

where a,b,c are symbols, and would like to parse it so that the floats are replaced with rationals like in

sqrt(pi)*(1/3*a + 1/3*b - 8/3*c**2)

I know how to do one by hand,

In[24] Rational(str(0.333333333333333)).limit_denominator(1000)

Out[24]: 1/3

but do not quite know how to go about parsing the atoms and picking only the ones that are floats, and substituting back the rational number approximation.

What is the smartest way of doing these substitutions in the expression?

Was it helpful?

Solution

Use nsimplify:

>>> print(nsimplify(sqrt(pi)*(0.333333333333333*a + 0.333333333333333*b - 2.66666666666667*c**2)))
sqrt(pi)*(a/3 + b/3 - 8*c**2/3)

OTHER TIPS

After a bit of fiddling, I think I have found a way to do it, but I am not sure that it will cover all the corner cases. At any rate here it is. Any suggestions for improvement?

import sympy
def rationalize_coeffs(expr):
    for i in expr.atoms(sympy.Float):
        r = sympy.Rational(str(i)).limit_denominator(1000)
        expr = expr.subs(i, str(r.p)+'/'+str(r.q))
    return expr    

if __name__=='__main__':
    # given a sympy expression expr
    x,y,z = sympy.symbols('x y z')
    # expr_orig = 2/57.*x + 3./4.*y + 3./4.*z
    expr = 0.0350877192982456*x + 0.75*y + 0.75*z

    print rationalize_coeffs(expr)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top