牛顿迭代法:介绍、原理与运用
牛顿迭代法:介绍、原理与运用
介绍
牛顿迭代法是一个可以求一个任意函数的零点的工具。它比二分法快得多。
公式是:x=a-f(a)/f'(a)。其中a是猜测值,x是新的猜测值。不断迭代,f(x)就越来越接近0。
原理
我们将f(x)做泰勒一阶展开:f(x)∼f(a)+(x-a)f'(a)。
令 | f(x) | = | 0 |
∴ | f(a)+(x-a)f'(a) | = | 0 |
∴ | f(a)+xf'(a)-af'(a) | = | 0 |
∴ | xf'(a) | = | af'(a)-f(a) |
∴ | x | = | a-f(a)/f'(a) |
实例:牛顿迭代法求√2的近似值
∵ | x = √2 |
∴ | x2 = 2 |
∴ | x2 -2 = 0 |
令f(x)=方程左边,则f(x)∼0↔x∼√2。
f'(x) = 2x。于是可以得到迭代公式:
x | |
= | a-f(a)/f'(a) |
= | a-(a2-2)/(2a) |
= | a-a/2+1/a |
= | a/2+1/a |
代码如下(要求误差小于1e-6):
#include <stdio.h> #include <math.h> int main(int argc, char const *argv[]) { double a = 2.0; double expect_error = 0.000001; double x; double actual_error; unsigned iteration_count = 0; do { if (a == 0.0) a = 0.1; /* 避免0做分母 */ x = a/2 + 1/a; actual_error = fabs(2 - x*x); a = x; ++iteration_count; printf("%d\t%.9f\t%.9f\n", iteration_count, a, actual_error); } while (actual_error >= expect_error); return 0; }
输出:
1 1.500000000 0.250000000 2 1.416666667 0.006944444 3 1.414215686 0.000006007 4 1.414213562 0.000000000
迭代了4次。用二分法呢?
1 1.500000000 0.250000000 2 1.250000000 0.437500000 3 1.375000000 0.109375000 4 1.437500000 0.066406250 5 1.406250000 0.022460938 6 1.421875000 0.021728516 7 1.414062500 0.000427246 8 1.417968750 0.010635376 9 1.416015625 0.005100250 10 1.415039062 0.002335548 11 1.414550781 0.000953913 12 1.414306641 0.000263274 13 1.414184570 0.000082001 14 1.414245605 0.000090633 15 1.414215088 0.000004315 16 1.414199829 0.000038843 17 1.414207458 0.000017264 18 1.414211273 0.000006475 19 1.414213181 0.000001080 20 1.414214134 0.000001617 21 1.414213657 0.000000269
二分法需要21次,而且精度还要差3位。
是不是二分法就一定比牛顿法慢呢?我测试了一下,发现不是的:
图中x轴是被开方的数,y轴为牛顿法、二分法开方这个数所用的迭代次数。
可以看出,某些时候二分法是比牛顿法快的。但是牛顿法的迭代次数要稳定一些。