如例
要计算方程 的解,要求:
(1) 设计一种收敛的不动点迭代法,然后再用Steffensen方法加速迭代;
(2) 利用Newton法计算;
要求近似解满足,输出迭代初值及各次迭代值和迭代次数,比较方法的优劣。
主程序
clc
clear
% 非线性方程求根
% 绘制函数图像
f=@(x) x.^2-3*x-exp(x)+2;
x=-2:0.1:2; %设置区间端点及步长
plot(x,y) %输出函数图像
grid on;
y=f(x);
% 多次画图,确定此函数有一个根,有根区间[0,0.5],初值取0.25
%%
fprintf('求方程x^2-3*x-exp(x)+2=0的解\n')
e=1.0e-8; % 误差精度;
x1=0.25; %初值
%% 用Steffensen方法求方程解
fprintf('Steffensen方法求方程解\n')
[root_steff1,ks1] = Steffensen(x1,e);
%% 用牛顿法求方程解
fprintf('牛顿迭代求方程解\n')
% 原函数和相应的一阶导数
f=@(x) x^2-3*x-exp(x)+2;
df=@(x)2*x-3-exp(x);
% f='x^2-3*x-exp(x)+2';
% df='2*x-3-exp(x)';
[root_new1,kn1] = newton(f,df,x1,e);
Steffensen方法加速迭代
function [root,k] = Steffensen(x0,e)
%%判断所选迭代格式是否收敛
fprintf('迭代格式为x(k+1)=(xk^2 + 2-exp(xk))/3\n')
f1=@(x)(x^2+2-exp(x))/3; % 迭代函数
df1=@(x)abs((2*x-exp(x))/3); %迭代函数相应的一阶导数的绝对值
x=0:0.01:0.5; %设置区间端点及步长 [0,0.5],步长取0.01
a = max(df1(x)); %区间内迭代函数一阶导数绝对值的最大值
if a < 1
fprintf('该迭代格式收敛\n')
else
fprintf('该迭代格式不收敛\n')
end
%%Steffensen方法加速迭代
fprintf('使用Steffensen方法加速迭代\n')
fprintf('迭代初值为x0=%.3f\n',x0) %输出初值
N=100; %N为迭代次数
x1=x0;
error=0.1;
k=0;
% 初值准备,其中误差项error为0.1是为了之后进去while循环的初始条件
while((error>e)&&(k<=N))
k=k+1;
y=f1(x1); %计算yk
z=f1(y); %计算zk
root=x1-(y-x1)^2/(x1-2*y+z); %迭代格式
error=abs(root-x1);
x1=root;
fprintf('迭代次数k=%.0f, x=%.12f, 迭代误差e=%.12f\n',k,x1,error)
end
fprintf('迭代总次数k=%.0f,近似解x*=%.12f\n\n\n',k,x1)
end
Newton法迭代
function [root,k] = newton(f,df,x0,e)
%root为牛顿迭代法输出的根,k为迭代次数,输入的x0为迭代初值,误差精度e
fprintf('迭代初值为x0=%.3f\n',x0) %输出初值
x1=x0;
k=0;
error_term=0.1;
% 初值准备,其中误差项error_term为0.1是为了之后进去while循环的初始条件
while((error_term>e)&&(k<=1000))
k=k+1;
fx=f(x1); %计算函数值
dfx=df(x1); %计算函数一阶导值
root=x1-fx/dfx; %迭代格式
error_term=abs(root-x1);
x1=root;
fprintf('迭代次数k=%.0f, x=%.12f, 迭代误差e=%.12f\n',k,x1,error_term)
end
fprintf('迭代总次数k=%.0f,近似解x*=%.12f',k,x1)
end
计算结果
优劣
初值取为0.25时,Steffensen和Newton迭代法均迭代3次达到,但第3次迭代的差值,明显Steffensen更小。
Steffensen加速法可将不收敛的迭代法,加速为收敛;也可将线性收敛迭代法,加速为2阶收敛。但Steffensen加速法一般不用于加速高阶收敛迭代法,因为加速效果不明显。而Newton收敛性依赖于x0的选取,如果x0偏离所求根x*太远,则牛顿法可能发散。