I'm using sympy to do a nonlinear solve over a set of power laws, and I end up with a bunch of solutions like
20394*sqrt(6)*x**(2/3)*y**(1/4)
I want to collapse the numerical coefficients while leaving the rational nature of the exponents exposed, i.e. I want my code to output
49954.8938143201*x**(2/3)*y**(1/4)
However, when I use evalf(), I get
49954.8938143201*x**0.666666666666667*y**0.25
Is there any way to ask sympy to not evaluate exponents, or even just to extract the non-symbolic part of the answer so I can create my own print function that formats output in the way I want?
One approach is to pick all Mul and Add subexpressions, separate their arguments into numeric and symbolic (based on whether any symbol is contained), and numerically evaluate the part with numeric arguments.
expr = 20394*sqrt(6)*x**(S(2)/3) + 3*log(3)*y**(S(3)/2) - 3*sqrt(7) + (3+sqrt(2))*x*y
eval_dict = {}
for a in expr.atoms(Mul, Add):
numeric = [arg for arg in a.args if not arg.has(Symbol)]
symbolic = [arg for arg in a.args if arg.has(Symbol)]
eval_dict[a] = a.func(a.func(*numeric).evalf(), a.func(*symbolic))
print(expr.subs(eval_dict))
This prints
49954.8938143201*x**(2/3) + 4.41421356237309*x*y + 3.29583686600433*y**(3/2) - 7.93725393319377
The rational exponents escape numeric evaluation, being instances of Rational.