import re
from math import gcd
from fractions import Fraction
RXP = r"(\s*[\+\-]\s*)?(\d*)(x?)(\d*)"
tests = ["2x2 - 5x + 2", "x2 + x - 6", "x + 5", "12x2 + 4x1 + 0x0"]
def rational_zeros(st):
poly = {}
for lst in re.findall(RXP, st):
if any(x != '' for x in lst):
a, b, c, d = lst
sgn = 1 if a == '' or a == ' + ' else -1
coef = int(b) if b != '' else 1
deg = 0
if c == 'x':
deg = int(d) if d != '' else 1
poly[deg] = sgn * coef
n = max(poly.keys())
m = min([k for k in poly.keys() if poly[k] != 0])
roots = []
if m > 0:
roots.extend([(0, 1)] * m)
poly = {k - m: poly[k] for k in poly.keys()}
n -= m
an, a0 = map(abs, (poly[n], poly.get(0, 0)))
def derive(fn):
return {k - 1: k * fn[k] for k in fn if k > 0}
def eval(fn, p, q):
return sum(fn[k] * p**k * q**(n - k) for k in fn)
ps = [d for d in range(1, a0 + 1) if a0 % d == 0]
qs = [d for d in range(1, an + 1) if an % d == 0]
for p in ps:
for q in qs:
for sgn in (1, -1):
if eval(poly, sgn * p, q) == 0:
g = gcd(p, q)
tu = (sgn * p // g , q // g)
if not tu in roots:
multiplicity = 0
m = dict(poly)
while 1:
if eval(m, tu[0], tu[1]) != 0:
break
m = derive(m)
multiplicity += 1
roots.extend([tu] * multiplicity)
return sorted([Fraction(x, y) for x, y in roots])
for test in tests:
p = rational_zeros(test)
print(p)
To embed this program on your website, copy the following code and paste it into your website's HTML: