牛顿迭代法(简写)就是一种近似求解实数域与复数域求解方程的数学方法。那么这个方法是具体是什么原理呢?本篇文章将会介绍如何用牛顿迭代法(Newton's method for finding roots)求方程的近似解,该方法于17世纪由牛顿提出。

具体的任务是,对于在[a,b]上连续且单调的函数f(x),求方程f(x)=0的近似解。


牛顿迭代如何迭代?

直接看数学公式描述如何迭代不直观,先来看动图就很容易理解牛顿迭代法为什么叫迭代法以及怎样迭代的:

牛顿迭代法是原理是根据一个初始点(x0,f(x0))在该点做切线,切线与X轴相交得出下一个迭代点x1的坐标,再在(x1,f(x1))处做切线,依次类推,直到求得满足精度的近似解为止。

牛顿迭代法

由前面描述知道,牛顿迭代法是用来近似求解方程的,这里有两个点需要说明:

(1)为啥要近似求解?很多方程可能无法直接求取其解

(2)迭代法非常适合计算机编程实现,实际上计算机编程对于牛顿迭代法广为应用

来看看,数学上如何描述的?

数学描述牛顿迭代法

其中牛顿迭代法为函数牛顿迭代法牛顿迭代法处的一阶导数,也就是该点的切线。

来简单推一推上面公式的由来,直线函数方程为:

直线函数方程

知道一个直线的一个坐标点直线函数方程以及斜率斜率则该直线的方程就很容易可以得知:

直线的方程

那么该直线与x轴的交点,就是y=0也即牛顿迭代法等式x的解:

等式x的解

啥时候停止迭代呢?

1. 计算出停止迭代

2. 给出一个初始假定根值根值,利用上面迭代式子进行迭代

迭代式子

3. 计算绝对相对迭代近似误差

计算绝对相对迭代

4. 将绝对相对近似误差与预定的相对误差容限容限进行比较。 如果迭代,则迭代步骤2,否则停止算法。 另外,检查迭代次数是否已超过允许的最大迭代次数。 如果是这样,则需要终止算法并退出。另一个终止条件是:

$$|f(x_{i+1})|如何编码呢?

由于牛顿迭代法主要目的是解方程,当然也有可能用于某一个数学函数求极值,所以无法写出通用的代码,这里仅仅给出一个编代码的思路。相信掌握了思路,对于各种实际应用应该能很快的写出符合实际应用的代码。

假定一函数为:

函数

其波形图如下:

19.png

其一阶导数为:

一阶导数

那么对于该函数的根:

函数的根

从图上大致可以知道有两个根,如果直接解方程,则很难求出其根,可以编个代码试试:

#include <stdio.h>
#include <math.h>
#include <stdlib.h>

/*假定待求根函数如下*/
#define    F(x)    (2*(x)*(x)-10*cos(x)+(x)-80)

/*其一阶导数为*/
#define   DF(x)    (4*(x)+10*sin(x)+1)

float newton_rooting(float x0,float precision,float min_deltax,int max_iterations)
{
     float xn,xn1,fn,fn1,dfn;
     float deltax;
     int step = 0;
     xn  = x0;
     xn1 = x0;
     do{
       xn  = xn1;
       fn  = F(xn);
       dfn = DF(xn);
       /*判0*/
       if( fabs(dfn) <1e-6 )
       {
            if( fabs(fn)>precision )
                return NAN;
            else
                return fn;
       }

       xn1 = xn - fn/dfn;
       fn1 = F(xn1);
       deltax = fabs(xn1-xn);
       
       step++;
       if( step>max_iterations )
       {
           if( fabs(fn1)<precision )
               return xn;
           else
               return NAN;
       }
     }
     while( fabs(fn1)>precision || deltax>min_deltax );

     return xn1;
}

void main()
{
     float root_guess = 23.0f;
     float precision = 0.00001f;
     float min_deltax = 0.001f;
     float root;
     int step = 7;

     root = newton_rooting( root_guess,precision,min_deltax,step );
     printf("根为: %f,函数值为:%f\n", root,F(root));

     root_guess = -23;
     root = newton_rooting( root_guess,precision,min_deltax,step );
     printf("根为: %f,函数值为:%f\n", root,F(root));
}

结果:

根为: 6.457232, 函数值为:0.000004
根为: -6.894969,函数值为:-0.000008

函数值已经很接近于0了,如果还需要更为精确的值,则可以选择在此基础上进一步求解,比如利用二分法逼近。


需要注意些啥?

求斜率可能为0,如为0时,则可能找到了函数的极值,比如:

函数的极值

如果选择的初始猜测根的接近方程f(x)=0中函数f(x)的拐点 ,Newton-Raphson方法可能开始偏离根。 然后,它可能会又收敛回到根。例如函数的极值

Newton-Raphson方法

如果选择的初值不合适,可能会跳掉一些根,比如:

Newton-Raphson方法

所以实际应用时,需要知道自己待求解模型的大致情况,在合理的加以调整。


有哪些应用?

比如知道某系统的传递函数,待求解其中的参数,可以将上述方法推而广之,求解多维变量方程组,求导就变成求偏导了

又比如设计一电路测量某物质的阻抗

....

总结一下

牛顿迭代法在解决实际问题时,利用迭代求方程近似根的数学原理,在工程中有着很好的实用价值。比如求一个趋势的极值,传递函数参数辨识等都有广泛的实际应用。


点赞(0)

C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:

一点编程也不会写的:零基础C语言学练课程

解决困扰你多年的C语言疑难杂症特性的C语言进阶课程

从零到写出一个爬虫的Python编程课程

只会语法写不出代码?手把手带你写100个编程真题的编程百练课程

信息学奥赛或C++选手的 必学C++课程

蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程

手把手讲解近五年真题的蓝桥杯辅导课程

Dotcpp在线编译      (登录可减少运行等待时间)