Halo

A magic place for coding

0%

非线性方程求解之牛顿法

介绍

  之前我介绍了使用二分法求解一个非线性方程,今天,我就来介绍另一种方法–牛顿法

分析

  牛顿法的核心思想是将非线性问题转化为线性问题处理。对于非线性方程f(x)=0,假设已知有近似根xk(假定f(xk)0),将函数f(x)在点xk进行泰勒展开,有
f(x)f(xk)+f(xk)(xxk)
于是方程f(x)=0可以近似地表示为
f(xk)+f(xk)(xxk)=0,
上面这个是一个线性方程,记其根为xk+1,则求得xk+1的计算公式为:
xk+1=xkf(xk)f(xk),
以上的迭代方法就称为牛顿法

代码实现

Matlab代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
% 牛顿法
function [y, count, error, time] = Newton(x, e)
% y为最终结果
% x为开始迭代的初始坐标
% e为迭代精度

del_x = 0.0000001; % 用于求函数导数值的极小量
count = [];% 输出迭代次数的数组
time = []; % 输出迭代时间的数组
error = [];% 输出误差的数组
k = 0; % 迭代次数变量
err = 0;% 误差变量
y = x;
x = y + 1000; % 保证迭代能开始
n = 50; % n为最大迭代次数
tic
while 1
if (abs(y-x) <= e)
disp('满足迭代精度');
break;
elseif (k > n)
disp('迭代次数过多,迭代结束');
break;
else
x = y;
if((myFun(x+del_x) - myFun(x)) == 0)
disp('导数为0');
break;
else
y_deriv = (myFun(x+del_x) - myFun(x)) / del_x; %x点的导数值
y = x - myFun(x) / y_deriv; % 牛顿迭代
k = k + 1; %迭代次数加1
count(k) = k;
err = abs(y-x) / y;
error(k) = err;
end
end
end
toc

% 均分时间间隔
temp = toc / k;
for i=1:k
time(i) = i*temp;
end

disp('牛顿迭代结束');
end


function [y] = myFun(x)
y = x*x - 115;
end

  其中myFun是需要求解的非线性方程。

小结

 求解上面代码中的非线性方程,即求115的值,其算法分析结果如下:
迭代步数与误差的关系
牛顿法结果1
计算时间与误差的关系
牛顿法结果2
  牛顿法的收敛速度要比二分法快很多,牛顿法在根x的邻近是平方收敛的,但在重根情况下,牛顿法只是线性收敛


参考资料:

1.数值分析(第5版) 李庆扬,王能超,易大义

Welcome to my other publishing channels

Powered By Valine
v1.5.2