This is exactly what real_roots done and is especially applicable to your case when the odds are integers:
x = Symbol('x') eq = int(row["scaleA"])*x**3 + int(row["scaleB"])*x**2 + int(row["scaleC"])*x + int(row["scaleD"]) y = real_roots(eq, x) # gives [CRootOf(...), ...]
The value of CRootOf instances can be estimated to whatever accuracy you need and should not contain any imaginary part. For instance,
>>> [in(12) for i in real_roots(3*x**3 - 2*x**2 + 7*x - 9, x)] [1.07951904858]
Note. As I recall, the decision will send back roots that it could not confirm by fulfilling the assumptions (i.e. if they were not recognized as false for the assumption, then they are returned). Also, if you want more consistent output from the solution, @PyRick, set the dict=True flag.
source share