Python | 牛顿法解一元方程
问题描述在日常生活中面对一元一次方程、一元二次方程甚至是一元三次方程时,我们都可以应用所学的数学知识比如因式分解和求根公式去将其轻易地解开。但并不是所有的方程都能进行因式分解或有求根公式又或者是求根公式复杂,这些问题都导致我们解方程时求解困难,形如x-cos(x)=0、e^x * sin(x)-cos(x)=0、x^4–2x^2+x=0等超越方程和高次方程我们人工计算就无法求得其解。解决方案我们可以应用牛顿法解决上述问题。牛顿法又称切线法,简单来说就是不断求函数图像的切线与x轴的交点,来逐渐接近函数解的一个迭代过程,其核心思想就是不断地逼近函数的解。牛顿法的步骤如下:.选取一个初始迭代点,如'1’;.根据公式

求出下一个接近零点的点;③重复步骤②直到满足:1).

(eps为人设的精度要求)2).达到最大迭代次数牛顿法的原理如图:

通过上图我们可以发现,每迭代一次

的值都将更接近方程的解。接下来我们用Python代码来实现牛顿法并求方程

的解:from sympy import *# 定义方程def function():x = symbols('x') # 符号变量的定义fx = -exp(x) * sin(x) + cos(x) - 1return fx# 求解方程的一阶导数def diff_funtion():fh = function()dth = fh.diff()return dth# 定义牛顿法def Newton(x0,eps,maxiter):# x1 = x0 - f(x0)/f`(x0) ==> x2 = x1 - f(x1)/f`(x1)x = symbols('x') # 符号变量的定义fh = function() #方程dfh = diff_funtion() #方程一阶导x_n = x0 # x_next代表x(n+1)print('%5s %14s %23s' %('迭代次数','计算结果','误差'))#利用牛顿法逐渐逼近精确解for k in range(maxiter):x_b = x_n # x_before代表x(n)fx = fh.evalf(subs = {x:x_b}) # 方程在xn处的数值dfx = dfh.evalf(subs = {x:x_b}) # 方程的一阶导在xn处的数值x_n = x_b - fx/dfxerrval = abs(fh.evalf(subs = {x:x_n})) #第k次迭代误差大小# 输出迭代过程print('%5d %25.15f %25.15f' % (k+1,x_n,errval))# 如果误差小于给定的精度要求,则退出if errval < eps:breakif k+1 <= maxiter-1:print('方程在满足精度' + str(eps) + '的条件下,近似解为:'+ str(x_n) + ',误差是:' + str(errval))else:print('牛顿迭代法求解数值逼近,已达到最大迭代次数,可能不收敛或精度过高...')fh = function()plot(fh) #画出函数图像x0 = float(input('请输入迭代初始值:'))eps = float(input('请输入方程解的精度要求:'))maxiter = int(input('请输入最大迭代次数:'))Newton(x0,eps,maxiter)运行结果如下:

用plot()画出函数图像方便选择迭代初始点

结语这里简单介绍了牛顿法,其本质是函数泰勒展开后,取一阶来近似,即用线性函数近似f(x),毕竟线性函数更好算。应用牛顿法我们几乎可以求解所有方程的近似解,而且精度极高。但通过上诉求方程-e^x*sin(x)+cos(x)-1=0的解我们可以看到牛顿法不能一次性求出所有的解,即当方程有多个解时,选择不同的初始迭代点得到方程的解就不同。作者:唐雷清实习编辑:李欣容稿件来源:深度学习与文旅应用实验室(DLETA)
