试位法 matlab程序,数值计算day2-求解非线性方程

上节课介绍了计算机中浮点数的表示方法,数值计算中涉及到的几种误差以及数值方法这门课中的一些数学基础。本节课将介绍如果使用数值方法来求解非线性方程。

1. MATLAB基本操作

>> % 生成序列

>> 1:5

ans =

1 2 3 4 5

>> % 清空所有变量,在脚本执行之前调用

>> clear all

>> % 函数定义方式1,在脚本文件中定义

function y = name(x)

... (commands)

end

>> % 函数定义方式2,函数句柄

>> f=@(x) x.^2

2. 应用背景

实际中,很多方程无法写出解析解,比如:

math?formula=e%5Ex%2Bsinx*x%5E5%20%3D%20900

064b869a915b

image

上图中,阴影部分的面积为,给定, ,求解对应的,即,无法得出解析解,MATLAB中,可以使用fzero计算出一个数值解:

>> f=@(x) 8-4.5*(x-sin(x))

f =

包含以下值的 function_handle:

@(x)8-4.5*(x-sin(x))

>> fzero(f,0)

ans =

2.4305

>> format long

>> fzero(f,0)

ans =

2.430465741723630

通常,求解非线性方程的方法有两类:一类是交叉法(bracketing methods),一类是开放法(open methods)。在交叉法中,先确定解所在的一个区间,利用数值算法,不断缩小该区间,直到区间两端点之间的距离小于一个给定的精度。在开放法中,通常先给出解的一个估计值,再利用数值算法,得出一个更精确的解。

064b869a915b

image

3. 数值解误差估计

在介绍一些数值解法之前,先介绍在数值解中误差的几种估计。由于数值解并不是真实解,因此必须使用一些误差估计原则来确定数值解的真实程度。假设

math?formula=x_%7BTS%7D

math?formula=f(x)%3D0真实解,即

math?formula=f(x_%7BTS%7D)%3D0

math?formula=x_%7BNS%7D为数值估计解,

math?formula=f(x_%7BNS%7D)%20%3D%20%5Cepsilon,有如下四种对误差的度量方式:

真实误差(True error):

math?formula=TrueError%20%3D%20x_%7BTS%7D-x_%7BNS%7D,真实误差难以计算,因为通常无法得到真实解

math?formula=f(x)的差值(Tolerance in

math?formula=f(x)):

math?formula=ToleranceInf%20%3D%20%7Cf(x_%7BTS%7D)-f(x_%7BNS%7D)%7C%3D%7C0-%5Cepsilon%7C%3D%7C%5Cepsilon%7C

解的差值(Tolerance in

math?formula=x):假设已知

math?formula=x_%7BTS%7D 在区间

math?formula=%5Ba%2Cb%5D之间,取

math?formula=%5Cfrac%7Ba%2Bb%7D%7B2%7D为数值解

math?formula=x_%7BNS%7D,则真实解与数值解的差值满足:

math?formula=%7Cx_%7BTS%7D-x_%7BNS%7D%7C%3C%5Cfrac%7Bb-a%7D%7B2%7D

相对误差(Relative error):

math?formula=TrueRelativeError%20%3D%20%7C%5Cfrac%7Bx_%7BTS%7D-x_%7BNS%7D%7D%7Bx_%7BTS%7D%7D%7C%2CEstimatedRelativeError%20%3D%20%7C%5Cfrac%7Bx%5E%7B(n)%7D_%7BNS%7D-x%5E%7B(n-1)%7D_%7BNS%7D%7D%7Bx%5E%7B(n-1)%7D_%7BNS%7D%7D%7C

4. 交叉法

4.1 二分法(Bisection method,依赖于介值定理)

给定区间

math?formula=%5Ba%2Cb%5D,假设

math?formula=f(x)连续且

math?formula=f(x)%3D0在该区间上有解。此时,

math?formula=f(x)在区间的那两个端点必定异号,即

math?formula=f(a)%3E0%2Cf(b)%3C0,或者

math?formula=f(a)%3C0%2Cf(b)%3E0,换句话说,如果

math?formula=x%3Da

math?formula=x%3Db之间有一个解,则

math?formula=f(a)f(b)%3C0

064b869a915b

image

算法步骤:

math?formula=f(a)f(b)%3C0, 取

math?formula=x_%7BNS%7D%3D%5Cfrac%7Ba%2Bb%7D%7B2%7D

如果

math?formula=f(x_%7BNS%7D)%3D0,算法停止;如果

math?formula=f(a)f(x_%7BNS%7D)%3C0,则令

math?formula=a%3A%3D%20a%2C%20b%3A%20%3D%20x_%7BNS%7D;如果

math?formula=f(b)f(x_%7BNS%7D)%3C0,则令

math?formula=a%3A%3D%20x_%7BNS%7D%2C%20b%3A%3D%20b

使用Tolerance in

math?formula=x 来决定停止准则,给定

math?formula=%5Cepsilon%3E0,当

math?formula=%5Cfrac%7Bb-a%7D%7B2%7D%3C%5Cepsilon时,停止

二分法的优缺点:

二分法总会收敛到一个解

math?formula=f(x)不穿过X轴时,无法使用

收敛速度较慢

MATLAB实现:

clear all

F = inline('8-4.5*(x-sin(x))');

a = 2; b = 3; imax = 20; tol = 0.001;

Fa=F(a); Fb=F(b);

if Fa*Fb > 0

disp('Error: The function has the same sign at points a and b.')

else

disp('iteration a b (xNS) Solution f(xNS) Tolerance')

for i = 1:imax

xNS = (a + b)/2;

toli=abs((b-a)/2);

FxNS=F(xNS);

fprintf('%3i %11.6f %11.6f %11.6f %11.6f %11.6f\n',i, a, b, xNS, FxNS, toli)

if FxNS == 0

fprintf('An exact solution x =%11.6f was found',xNS)

break

end

if toli < tol

break

end

if i == imax

fprintf('Solution was not obtained in %i iterations',imax)

break

end

if F(a)*FxNS < 0

b = xNS;

else

a = xNS;

end

end

end

% 运行结果

>> Program_3_1

iteration a b (xNS) Solution f(xNS) Tolerance

1 2.000000 3.000000 2.500000 -0.556875 0.500000

2 2.000000 2.500000 2.250000 1.376329 0.250000

3 2.250000 2.500000 2.375000 0.434083 0.125000

4 2.375000 2.500000 2.437500 -0.055709 0.062500

5 2.375000 2.437500 2.406250 0.190661 0.031250

6 2.406250 2.437500 2.421875 0.067838 0.015625

7 2.421875 2.437500 2.429688 0.006154 0.007813

8 2.429688 2.437500 2.433594 -0.024755 0.003906

9 2.429688 2.433594 2.431641 -0.009295 0.001953

10 2.429688 2.431641 2.430664 -0.001569 0.000977

4.2 线性插值法(Regula Falsi Method, 试位法)

将两点

math?formula=(a%2Cf(a))%2C(b%2Cf(b))之间的连线与

math?formula=X轴的交点作为估计点:

064b869a915b

image

给定区间,与之间连线的方程为 令,得 后续的算法过程与二分法一致。

MATLAB中的fzero函数就是采用以上两种交叉法求解非线性方程的,而对于多项式方程

MATLAB提供如下命令来进行求解:

root([a_n a_{n-1} ... a_1 a_0])

>> roots([1 2 -3])

ans =

-3.0000

1.0000

5. 开放法

5.1 牛顿法(Newton's method)

对连续可导函数

math?formula=f(x),假设知道

math?formula=f(x)%3D0在一个给定点附近有一个解,则可以使用牛顿法来估计解:

064b869a915b

image

首先选取一个点作为解的初始估计值,第二个估计点通过取在点处的切线与轴的交点得到,同理得到后续的估计点。注意,在第一次迭代过程中,斜率 因此, 于是牛顿迭代法可以写出如下通解形式:

停机准则:牛顿法通常使用估计值的相对误差来作为停止条件

math?formula=%7C%5Cfrac%7Bx_%7Bi%2B1%7D-x_i%7D%7Bx_i%7D%7C%5Cleq%20%5Cepsilon

牛顿法的优缺点:

给定一个比较好的初始估计,算法收敛速度会很快

初始估计不够好,则无法保证算法会收敛

064b869a915b

image

当函数的导数无法给出解析式时,需要设计求导算法

例:方程

math?formula=%5Cfrac%7B1%7D%7Bx%7D-2%3D0的解为

math?formula=x%3D0.5,使用牛顿法求解:

迭代公式为:

math?formula=x_%7Bn%2B1%7D%3Dx_n-%5Cfrac%7Bf(x_n)%7D%7Bf'(x_n)%7D%3Dx_n-%5Cfrac%7B%5Cfrac%7B1%7D%7Bx_n%7D-2%7D%7B%5Cfrac%7B1%7D%7Bx_n%5E2%7D%7D%3Dx_n%2Bx_n%5E2(%5Cfrac%7B1%7D%7Bx_n%7D-2)%3Dx_n%2Bx_n-2x_n%5E2%3D2x_n(1-x_n)

math?formula=x_1%3D1.4,

math?formula=x_2%20%3D%202*1.4*(-0.4)%3D-1.12,

math?formula=x_3%3D2*x_2(1-x_2)%3D-4.7488,不收敛

math?formula=x_1%3D1,

math?formula=x_2%20%3D%202*1*0%3D0,

math?formula=x_3%3D2*0*1%3D0,收敛到

math?formula=0

math?formula=0不是解

math?formula=x_1%3D0.4,

math?formula=x_2%3D2*0.4*0.6%3D0.48,

math?formula=x_3%3D2*0.48*(1-0.48)%3D0.4992,收敛

MATLAB实现

function Xs = NewtonRoot(Fun,FunDer,Xest,Err,imax)

% NewtonRoot finds the root of Fun = 0 near the point Xest using Newton's method.

% Input variables:

% Fun Handle of a user-defined function that calculates Fun for a given x.

% FunDir Handle of a user-defined function that calculates the derivative

% of Fun for a given x.

% Xest Initial estimate of the solution.

% Err Maximum error.

% imax Maximum number of iterations

% Output variable:

% Xs Solution

for i = 1:imax

Xi = Xest - Fun(Xest)/FunDer(Xest);

if abs((Xi - Xest)/Xest) < Err

Xs = Xi;

break

end

Xest = Xi;

end

i

if i == imax

fprintf('Solution was not obtained in %i iterations.\n',imax)

Xs = ('No answer');

end

%%%%%%%%%%%%%%%%%%%%%%%%%%

>> format long

>> f=@(x) 8-4.5*(x-sin(x))

f =

包含以下值的 function_handle:

@(x)8-4.5*(x-sin(x))

>> fder=@(x) -4.5*(1-cos(x))

fder =

包含以下值的 function_handle:

@(x)-4.5*(1-cos(x))

>> NewtonRoot(f,fder,2,1e-6,100)

i =

4

ans =

2.430465741723630

5.2 割线法(Secant method)

割线法使用两个与解临近的初始点来估计一个新的解。假设初始点为

math?formula=x_1

math?formula=x_2,穿过这两个点的直线与

math?formula=X轴的交点就被作为新的估计值

math?formula=x_3,这两个初始点的可以在解的同侧,也可以在不同侧:

064b869a915b

image

穿过与的直线满足: 因此, 不断迭代下去,迭代公式为:

064b869a915b

image

MATLAB实现:

function Xs = SecantRoot(Fun,Xa,Xb,Err,imax)

% SecantRoot finds the root of Fun = 0 using the Secant method.

% Input variables:

% Fun Name of a user-defined function that calculates Fun for a given x.

% a, b Two points in the neighborhood of the root (on either side, or the

% same side of the root).

% Err Maximum error.

% imax Maximum number of iterations

% Output variable:

% Xs Solution

for i = 1:imax

FunXb = Fun(Xb);

Xi = Xb - FunXb*(Xa-Xb)/(Fun(Xa)-FunXb);

if abs((Xi - Xb)/Xb) < Err

Xs = Xi;

break

end

Xa = Xb;

Xb = Xi;

end

if i == imax

fprintf('Solution was not obtained in %i iterations.\n',imax)

Xs = ('No answer');

end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

>> format long

>> f=@(x) 8-4.5*(x-sin(x))

f =

包含以下值的 function_handle:

@(x)8-4.5*(x-sin(x))

>> SecantRoot(f,2,3,0.0001,10)

ans =

2.430465726588755

5.3 固定点迭代法(Fixed-point iteration method)

使用固定点迭代法求解方程的需要将方程改写为:

math?formula=x%3Dg(x) 最简单的改写方法是

math?formula=f(x)%3D0%20%5Crightarrow%20x%20%3D%20f(x)%2Bx%3Dg(x) ,显然若

math?formula=x

math?formula=f(x)%3D0的解,则必有

math?formula=x%3Dg(x),改写后得到的方程可以通过绘图来求解:

064b869a915b

image

两条线的交点称作是固定点(Fixed point),初始估计点取在固定点附近,下一步则将的值作为新的估计值,一直迭代下去:

064b869a915b

image

064b869a915b

image

在固定点迭代法中,迭代函数不是唯一的,有的迭代函数可能导致方法不收敛,固定点收敛的条件为:

064b869a915b

image

例:

math?formula=xe%5E%7B0.5x%7D%2B1.2x-5%3D0,使用固定点法求解(

math?formula=x%3D1%2Cx%3D2)

math?formula=1.2x%3D5-xe%5E%7B0.5x%7D

math?formula=x%3D%5Cfrac%7B5-xe%5E%7B0.5x%7D%7D%7B1.2%7D%3Dg(x) 此时

math?formula=g'(x)%3D-(e%5E%7B0.5x%7D%2B0.5xe%5E%7B0.5x%7D)%2F1.2

math?formula=g'(1)%3D-2.0609%2Cg'(2)%3D-4.5305,算法不收敛

math?formula=x_2%20%3D%20%5Cfrac%7B5-1e%5E%7B0.5%7D%7D%7B1.2%7D%3D2.7927%2Cx_3%3D%5Cfrac%7B5-2.7927e%5E%7B0.5*2.7927%7D%7D%7B1.2%7D%3D-5.2364

math?formula=x_4%3D%5Cfrac%7B5-(-5.2364)e%5E%7B0.5*(-5.2364)%7D%7D%7B1.2%7D%3D4.4849%2Cx_5%3D%5Cfrac%7B5-4.4849e%5E%7B0.5*4.4849%7D%7D%7B1.2%7D%3D-31.0262

math?formula=x(e%5E%7B0.5x%7D%2B1.2)%3D5

math?formula=x%3D%5Cfrac%7B5%7D%7Be%5E%7B0.5x%7D%2B1.2%7D%3Dg(x)

math?formula=g'(x)%3D%5Cfrac%7B-5e%5E%7B0.5x%7D%7D%7B2(e%5E%7B0.5x%7D%2B1.2)%5E2%7D,

math?formula=g'(1)%3D-0.5079%2Cg'(2)%3D-0.4426,算法收敛

math?formula=x_2%3D%5Cfrac%7B5%7D%7Be%5E%7B0.5%7D%2B1.2%7D%3D1.7552%2Cx_3%3D%5Cfrac%7B5%7D%7Be%5E%7B0.5*1.7552%7D%2B1.2%7D%3D1.3869

math?formula=x_4%3D%5Cfrac%7B5%7D%7Be%5E%7B0.5*1.3869%7D%2B1.2%7D%3D1.5622%2Cx_5%3D%5Cfrac%7B5%7D%7Be%5E%7B0.5*1.5622%7D%2B1.2%7D%3D1.4776

math?formula=x_6%3D%5Cfrac%7B5%7D%7Be%5E%7B0.5*1.4776%7D%2B1.2%7D%3D1.5182%2Cx_7%3D%5Cfrac%7B5%7D%7Be%5E%7B0.5*1.5182%7D%2B1.2%7D%3D1.4986

math?formula=xe%5E%7B0.5x%7D%3D5-1.2x

math?formula=x%3D%5Cfrac%7B5-1.2x%7D%7Be%5E%7B0.5x%7D%7D

math?formula=g'(x)%3D%5Cfrac%7B-3.7%2B0.6x%7D%7Be%5E%7B0.5x%7D%7D

math?formula=g'(1)%3D-1.8802%2Cg'(2)%3D-0.9197,算法不收敛

初始点可以通过画图进行估计:

>> f=@(x) x.*exp(0.5*x)+1.2*x-5

f =

包含以下值的 function_handle:

@(x)x.*exp(0.5*x)+1.2*x-5

>> x = linspace(0,3,100);

>> plot(x,f(x))

>> xlabel('x');

>> ylabel('f(x)');

>> title('f(x)=xe^{x/2}+1.2x-5');

064b869a915b

image

6. 总结

本节课主要介绍了求解非线性方程的几种方法,主要分为两类,一类是交叉法,包括二分法、线性插值法,这类方法的停止条件通常采用解的差值准则;一类是开放法,包括牛顿法、割线法以及固定点法,这类方法的停止准则主要采用估计值的相对误差来规定。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值