Task:牛顿-拉夫逊定理——牛顿迭代法求解多项式的近似根(通用多项式)
这里因为是英语,需要大家慢慢看呀,了解下这个Task的目的,如果不了解牛顿-拉夫逊定理的,推荐大家到这里观看:如何通俗易懂地讲解牛顿迭代法求开方?数值分析? - 知乎
- coefficients是多项式系数组成的元组,可以是二阶、三阶甚至更高阶
- guess是猜测的值
- epsilon是误差(即当下列式子符合时,输出结果)
题目是学校的python课程的题目,一共是5道题目,均是初等的算法题目,有需要的朋友在这里下载:下载链接
思路:
- 判断输入的多项式是否有解(利用到了有理根定理),代码中的Judge_Root()函数
- 计算代入guess的多项式的值(记为fnx),代码中的fnx()函数
- 计算代入guess的多项式求导后的值(记为fndx),代码中的fndx()函数
- 判断fnx是否为0,如果为0,则guess为根(直接输出)
- 判断fndx是否为0,如果为0,则表示guess是多项式的驻点,即其切线平行于x轴(重新输入guess)
- 将 |-fnx/fndx|与epsilon比较
- 如果 |-fnx/fndx|<epsilon ,输出此刻的guess值
- 如果 |-fnx/fndx|>epsilon ,视情况而定对guess重新赋值,然后再次运行函数NR_Root
代码:
def Judge_Root(coefficients):
coe = coefficients
if coe[-1] == 0:
return True
if type(coe[0]) != int or type(coe[-1]) != int:
max_multi = max(len(str(coe[0]).split(".")[-1]), len(str(coe[-1]).split(".")[-1]))
coe = [(10**max_multi) * i for i in coe]
numerator_list = [i for i in range(1, abs(coe[-1]) + 1) if abs(coe[-1]) % i == 0]
denominator_list = [i for i in range(1, abs(coe[0]) + 1) if abs(coe[0]) % i == 0]
for i in numerator_list:
for x in denominator_list:
for y in [1, -1]:
try_num = y * i / x
if fnx(coefficients, try_num) == 0:
return True
return False
def fnx(coefficients, x):
coe = coefficients
fnx_sum = 0
for i in range(len(coe)):
fnx_sum += coe[i] * (x ** (len(coe) - i - 1))
return fnx_sum
def fndx(coefficients, x):
coe = coefficients
fndx_sum = 0
for i in range(1, len(coe)):
fndx_sum += coe[i - 1] * (x ** (len(coe) - i - 1)) * (len(coe) - i)
return fndx_sum
def NR_Root(coefficients, guess, epsilon):
fx = fnx(coefficients, guess)
fdx = fndx(coefficients, guess)
# This step is to determine whether the polynomial has real roots
if not Judge_Root(coefficients):
return "Polynomials have no real roots"
if fx == 0.0:
return f"Root: {guess}"
elif fdx == 0.0:
return "The GUESS value is not available because GUESS is a stagnation point, or GUESS ±(n*1) is a stagnation point "
elif abs(guess - fx / fdx - guess) < epsilon:
return guess
elif (- fx / fdx) < 0:
guess = guess - 1
return NR_Root(coefficients, guess, epsilon)
else:
guess = guess + 1
return NR_Root(coefficients, guess, epsilon)
if __name__ == '__main__':
Coefficients = (1, 1, -12)
Guess = -5
Epsilon = 0.5
print(NR_Root(Coefficients, Guess, Epsilon))