Search code examples
pythonpython-3.xsympyfloating-accuracy

Finding Rational Root of Polynomial in Python


I am having a little issue regarding solving polynomial in python's sympy.solvers. What I want is to find the rational root, not irrational root. my attempt is given below -

from sympy.solvers import solve
from sympy import Symbol
from fractions import Fraction

b_2=0
b_4= -10
b_6=32
b_8=-25

x_2p=-7/4

x = Symbol('x', real=True)
solution=solve(((4*x**3+b_2*x**2+2*b_4*x+b_6)*x_2p-(x**4-b_4*x**2-2*b_6*x-b_8)), x)
R=solution
if len(R) != 0:
    print(Fraction(R[1]))

I got below error -

Traceback (most recent call last):
  File "C:\Users\Roy\Desktop\EXP_2704 - Copy.py", line 16, in <module>
    print(Fraction(R[1]))
  File "C:\Program Files\Python37\lib\fractions.py", line 161, in __new__
    raise TypeError("argument should be a string "
TypeError: argument should be a string or a Rational instance

Note that I need to get accurate fraction from floating.

How can I find rational root?


Solution

  • If you use real_roots you will get a CRootOf instance that can be computed with arbitrary precision. Using your initialization and the following I get:

    >>> from sympy import Rational, real_roots
    >>> eq = ((4*x**3+b_2*x**2+2*b_4*x+b_6)*x_2p-(x**4-b_4*x**2-2*b_6*x-b_8)); eq
    -x**4 - 7.0*x**3 - 10*x**2 + 99.0*x - 81.0
    >>> real_roots(_)
    [1, CRootOf(x**3 + 8*x**2 + 18*x - 81, 0)]
    >>> r=_[1]
    >>> Rational(r.n(2))
    133/64
    >>> Rational(r.n(20))
    613677434358103191805/295147905179352825856