How do I replace floats with rationals in a sympy expression?
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?
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