何为牛顿迭代法

牛顿迭代法又称为牛顿-拉弗森方法,是牛顿在17世纪提出的一种在实数和复数域上近似求解方程的方法。
牛顿迭代法的操作简单来说就是通过不断取切线,然后通过切线再不断逼近相应的解,废话不多说,我们来看例子。
例如如下曲线 \(y=x^2-1\)。

牛顿拉夫逊迭代法python 牛顿拉夫逊迭代法步骤_牛顿拉夫逊迭代法python

我们在其上面任取一点,不妨取点\(A(2,3)\),以该点做切线,切线方程为 \(y=4x-5\),在图中将该切线加上可得如下图:

牛顿拉夫逊迭代法python 牛顿拉夫逊迭代法步骤_牛顿迭代法_02

然后取其与x轴的交点\(B(1.25, 0)\),可见,第一次做切线取到的根已经开始接近原曲线的其中一个根,继续以该点做垂线,交原曲线与点\(C(1.25,0.5625)\),如图:

牛顿拉夫逊迭代法python 牛顿拉夫逊迭代法步骤_迭代_03

以点\(C(1.25,0.5625)\)再一次做原曲线的切线,该切线交x轴于点\(D(1.025, 0)\),如下图,可见,相较于点 \(B\),和原曲线与x轴的交点\(E(1, 0)\)进一步接近。
同理,接下来继续迭代,则通过不断做切线,切线与x轴取交点,取到的近似解会与其真实解越来越接近。

牛顿拉夫逊迭代法python 牛顿拉夫逊迭代法步骤_牛顿迭代法_04

宏观图

牛顿拉夫逊迭代法python 牛顿拉夫逊迭代法步骤_牛顿迭代法_05

微观图


迭代公式

通过上面的推导,我们很容易能够看出,所谓牛顿迭代法,就是不断利用切线对其解不断逼近,那么我们就需要一次次求切线,切线的求法如下:

设曲线方程为 \(y=f(x)\),可知其斜率为 \(y'=f'(x)\),任意取一点 \((x_0, y_0)\) ,则该点处的切线方程为 \(y - f(x_0) = f'(x_0) * (x - x_0)\),然后取切线与x轴的交点,故令 \(y_1 = 0\),代入解得 \(x_1 = x_0 - \frac{f(x_0)} { f'(x_0)}\),\(x_1\)是在\(x_0\)的基础上推出来的下一个逼近的根,同理,在此迭代公式的基础上继续迭代即可,直到所要求的的精度达到要求。


C++编程实例

(1)使用牛顿迭代法求解x^3 + 2x^2 + 3x + 4 = 0在1附近的根。

(2)使用牛顿迭代法求三次根号的解

#include <iostream>
#include <iomanip>
using namespace std;

/*
    使用牛顿迭代法求解x^3 + 2x^2 + 3x + 4 = 0在1附近的根
*/
double fun(double x1) {
    double x2 = 0;          // 第二次取近似根的值,不为1的任意值都可以
    double acc = 10e-5;     // 精度
    while (fabs(x1 - x2) > acc) {   // 对比两次根的跨度,看是否收敛
	x2 = x1;
	x1 = x1 - (x1 * x1 * x1 + 2 * x1 * x1 + 3 * x1 + 4)
               / (3 * x1 * x1 + 4 * x1 + 3);   // 牛顿迭代法迭代
    }
    return x1;
}

/*
    使用牛顿迭代法求三次根号的解 -> y = x^3 -> x^3 - y = 0 求解x
    即求 f(x) = x^3 - a 的零点,其中a为待求三次根号的数
*/
double cubeRoot(double x)                   // 牛顿迭代法  f(x[n]) + f'(x[n])(x - x[n]) = 0
{                                           //           ->f(x[n]) + f'(x[n])(x[n+1] - x[n]) = 0
    double yn = 1, yp = x;
    double acc = 10e-5;
    while (fabs(yp - yn) > acc)
    {
        yn = yp;
        yp = yp - (yp * yp * yp - x) / (3 * yp * yp);
    }
    return yp;
}

int main() {
    cout << fixed << setprecision(10);
    cout << cubeRoot(3) << endl;
    cout << fun(1) << endl;

    return 0;
}