牛顿迭代法求解
何为牛顿迭代法
牛顿迭代法又称为牛顿-拉弗森方法,是牛顿在17世纪提出的一种在实数和复数域上近似求解方程的方法。
牛顿迭代法的操作简单来说就是通过不断取切线,然后通过切线再不断逼近相应的解,废话不多说,我们来看例子。
例如如下曲线 \(y=x^2-1\)。
我们在其上面任取一点,不妨取点\(A(2,3)\),以该点做切线,切线方程为 \(y=4x-5\),在图中将该切线加上可得如下图:
然后取其与x轴的交点\(B(1.25, 0)\),可见,第一次做切线取到的根已经开始接近原曲线的其中一个根,继续以该点做垂线,交原曲线与点\(C(1.25,0.5625)\),如图:
以点\(C(1.25,0.5625)\)再一次做原曲线的切线,该切线交x轴于点\(D(1.025, 0)\),如下图,可见,相较于点 \(B\),和原曲线与x轴的交点\(E(1, 0)\)进一步接近。
同理,接下来继续迭代,则通过不断做切线,切线与x轴取交点,取到的近似解会与其真实解越来越接近。
迭代公式
通过上面的推导,我们很容易能够看出,所谓牛顿迭代法,就是不断利用切线对其解不断逼近,那么我们就需要一次次求切线,切线的求法如下:
设曲线方程为 \(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;
}