问题
给定一个整数系数的多项式,我们要得到所有的有理数解x,使得x代入多项式为0。有理数解就是能用分数表示的解。
解题思路
如果有理数解为p/q,则多项式可分解成若干个(x-p/q)相乘的形式,其中p是多项式常数项系数的因数,q是多项式最高次项系数的因数。这样分解之后x=p/q就是我们需要求的有理数解,所以只需要尝试所有p、q的组合,判断p/q是否满足多项式为0,即可。需要注意的是,(1)要考虑负根(2)不能去掉重根,应该把所有的重根都列出来。
代码如下:
#方程式求有理数根
import math
import fractions
def add_poly(L1,L2):#多项式加法
R=[]
if len(L1)>len(L2):
L1,L2=L2,L1
i=0
while i<len(L1):
R.append(L1[i]+L2[i])
i+=1
R=R+L2[len(L1):len(L2)]
return R
def subtract_poly(L1,L2):#多项式减法
R=[]
L2=L2[:]#为了不改变原来的L2
for i in range(len(L2)):
L2[i]=-L2[i]
R=add_poly(L1,L2)
return R
def multiply_poly(L1,L2):#多项式乘法
if len(L1)>len(L2):
L1,L2=L2,L1
zero=[];R=[]
for i in L1:
T=zero[:]
for j in L2:
T.append(i*j)
R=add_poly(R,T)
zero=zero+[0]
return R
def divide_poly(L1,L2):#多项式除法
if len(L1)<len(L2):return [0]
d=len(L1)-len(L2)
T=L1[:];R=[]
for i in range(d+1):
n=T[len(T)-1]/L2[len(L2)-1]
R=[n]+R
T1=[0]*(d-i)+[n]
T2=multiply_poly(T1,L2)
T=subtract_poly(T,T2)
T=T[:len(T)-1]
return R
def check(L,s):#检查根代入方程式是否为0
sum1=0
for t in range(len(L)):
if t==0:sum1=sum1+L[t]
else:sum1=sum1+L[t]*s**t
if abs(sum1)<1e-15:return True #检查sum1是否和0相等,一个小数的绝对值小于le-15就近似等于0.
else:return False
#if round(sum1, 20) < 1e-15:
# return True
#else:
# return False
def rational(L):
R=[]#存放最高次项系数的因数
T=[]#存放常数项系数的因数
S=[]#存放结果
#求出次数最高次项系数的因数存放在R中
k1=1
while k1<=math.sqrt(abs(L[len(L)-1])):
q=L[len(L)-1]/k1
if int(q)==q:
if q==k1 :
R.append(int(q))
else:
R.append(k1)
R.append(int(q))
k1=k1+1
#print(R)
#求出常数项的所有因数存放在T中
k2=1
while k2<=math.sqrt(abs(L[0])):
p=L[0]/k2
if int(p)==p:
if p==k2 :
T.append(int(p))
else:
T.append(k2)
T.append(int(p))
k2=k2+1
#print(T)
for i in T:
for j in R:
s1 = fractions.Fraction(i, j)#s1=i/j
while check(L,s1):#用while循环主要是为了不去除重根
S.append(s1)
L=divide_poly(L,[-s1,1])#得到一个根之后就去除去一个因式ax-1,更新被除数
#print(1,L,S)
s2 = fractions.Fraction(-i, j)#s2是为了验证负根s2=-i/j
while check(L,s2):
S.append(s2)
L=divide_poly(L,[-s2,1])
#print(2,L,S)
#print(S)
return S
def to_String(S):#把多项式列表转化成表达式
str1=""
for x in S:
if x==0:str1="x"
elif x>0:
str1="(x-"+str(x)
else :str1="(x+"+str(abs(x))
str1=str1+")"
print(str1,end="")
print("\n")
while True:
s=input("请输入一个方程式的系数(低次项系数在前,以空格分隔)")
L1=s.split(" ")
L=[int(e) for e in L1]
print("L:",L)
S=rational(L)
if len(S)==0:
print("No solution!\n")
else:
print("方程分解成有理数根的形式是:",end="")
to_String(S)