Chapter 7 MATLAB 在计算方法中的应用7.1 插值7.1.1 Lagrange 插值 对给定的 n 个自变量 x1, x2, …, xn 及对应的 函数值 y1, y2, …, yn, 求插值区间内任意 x 的函
数 值 y。 lagrange 插值公式:
y(x)= ∑ yk(∏ )
n
k=1
n
j=1j≠k
x-xj
xk-xj
将上述插值公式编写成 M 文件,取名 lagrange.m
句法结构:function y=lagrange(x0,y0,x)
n=length(x0);m=length(x);
for i=1:m
z=x(i);
s=0.0;
for k=1:n
p=1.0;
for j=1:n
if j~=k
p=p*(z-x0(j))/(x0(k)-x0(j));
end
end
s=p*y0(k)+s;
end
y(i)=s;
end
例 1: x=0:0.2:2*pi; y=sin(x);x1=0:0.1:2*pi;
插值: y1=lagrange(x,y,x1);
精确值: y2=sin(x1);
检查插值效果: plot(x,y,’r’,x1,y1,’bo’)
plot(x1,y1-sin(x1))
例 2: x=[-5:1:5]; y=1./(1+x.^2);x0=[-5:0.1:5];
插值: y0=lagrange(x,y,x0);
精确值: y1= 1./(1+x0.^2);
检查插值效果: plot(x0,y0,’--r’,x0,y1,’-b’)
7.1.2 一维插值命令 interp1
句法结构: y=interp1(x0,y0,x)
例:将上例中的 lagrange 换成 interp1, 其他相同。
nearest: 线性最近项插值, linear: 线性插值 spline: 三次样条插值, cubic :三次插值。
例 正弦曲线的插值示例。>>x=0:0.1:10;>>y=sin(x);>>xi=0:.25:10;>>yi=interp1(x,y,xi);>> plot(x,y,’0’,xi,yi)
例 计算上例的函数插值>>y2=interp1(x,y,x0);>>plot(x0,y2.’*m’)
7.1.3 Hermite 插值
1. 方法介绍
已知 n 个插值节点 x1,x2,…, xn 及其对应的函数值 y1,y2,…,yn 和一阶导数值 y‘1,y’2,…,y‘n 。则计算插值区域内任意 x 的函数值 y的 Hermite 插值公式:
hhh
n
iji ji
i
n
ijj ji
ji
iiiii
n
ii
xxxx
xxh
yyyxxhxy
1
2
1
1
1;)(
])2)([()(
其中
2 MATLAB 实现 hermite.m function y=hermite(x0,y0,y1,x)%hermite insert n=length(x0);m=length(x); for k=1:m yy=0.0; for i=1:n h=1.0; a=0.0; for j=1:n if j- =i h=h*((x(k)-x0(j))/(x0(i)-x0(j)))^2;
a=1/(x0(i)-x0(j))+a; end end yy=yy+h*((x0(i)-x(k))*(2*a*y0(i)-y1(i))+y0(i)); end y(k)=yy; end例 Hermite 插值示例。对给定数据表如表 7.2所示,试构造 Hermite 多项式,并给出 sin0.34的近似值。
>> x0=[0.3 0.32 0.35];>>y0=[0.29552 0.31457 0.34290];
>>y1=[0.95534 0.94924 0.93937];>>x=[0.3:0.005:0.35];>>y=hermite(x0,y0,y1,x);>>plot(x,y)>>hermite (x0,y0,y1,0.34);>>y
>>sin(0.34) >>y2=sin(x);>>hold on>>plot(x,y2,’--r’)
7.1.4 三次样条插值1 方法介绍设区间 [a,b] 上给定有关划分 a=x0<x1<…<xn=b,S 为[a,b]上满足下列条件的函数 .S C∈ 2 (a,b);S 在每个子区间 [xi,xi+1 ] 上是三次多项式 .
则称 S 关于划分的三次样条函数 . 常用的三次样条函数的边界条件有三种类型 :I 型 II 型
.)(,0)( 0 nfxSfxS n ,)(,0)( 0 nfxSfxS n 其特殊情况为
。0)( 0 nxSxS
Ⅲ 型 ,,,, 3210),()( 0 jxSxS njj 此条件称为周期样条函数 .
2 MATLAB 实现Spline2.m function s=spline2(x0,y0,y21,y2n,x) n=length(x0); km=length(x); a(1)=-0.5; b(1)=3*(y0(2)-y0(1))/(2*(x0(2)-x0(1))); for j=1:(n-1) h(j)=x0(j+1)-x0(j); end for j=2:(n-1) alpha(j)=h(j-1)/(h(j-1)+h(j));
beta(j)=3*((1-alpha(j))*(y0(j)-y0(j-1))/h(j-1)+…
alpha(j)*(y0(j+1)-y0(j))/h(j));
a(j)=-alpha(j)/(2+(1-alpha(j))*a(j-1));
b(j)=(beta(j)-(1-alpha(j))*b(j-1))/(2+(1-alpha(j))*a(j-1));
end
m(n)=(3*(y0(n)-y0(n-1))/h(n-1)+y2n*h(n-1)/2-b(n-1))/(2+a(n-1));
for j=(n-1):-1:1
m(j)=a(j)*m(j+1)+b(j);
end
for k=1:km
for j=1:(n-1)
if((x(k)>=x0(j))&(x(k)<x0(j+1)))
1(k)=j;
end
end
end
for k=1:km
sum=(3*(x0(1(k)+1)-x(k))^2/h(1(k))^2-…
2*(x0 (1(k)+1)-x(k))^3 /h(1(k))^3)*y0(1(k));
sum=sum+(3*(x(k)-x0(1(k)))^2/h(1(k))^2-…
2*(x(k)-x0(1(k)))^3/h(1(k))^3/h(1(k))^3)*y0(1(k)+1);
sum=sum+h(1(k))*((x0(1(k)+1)-x(k))^2/h(1(k))^2-…(x0(1(k) +1)-x(k))^3/h(1(k)^3)*m(1(k));
s(k)=sum-h(1(k))*((x(k)-x0(1(k)))^2/h(1(k))^2-…
(x(k)-x0(1(k)))^3/h()1(k))^3)*m(1(k)+1);
end
例 给定如下数据表所示的数据,试求三次样插值函数满足边界条件 s〞 (28.7)= s〞(30)=0. 表X 28.7 28 29 30
Y 4.1 4.3 4.1 3.0
>>x=[28.7 28 29 30];
>>y=[4.1 4.3 4.1 3.0];
>>x0=[28.7:0.15:30];
>>y=spline2(x,y,0,0,x0);
>>plot(x0,y)
7.1.5 最小二乘法拟合1 利用 polyfit 函数进行拟合 例: x=[0.5 1.0 1.5 2.0 2.5 3.0];
y=[1.75 2.45 3.81 4.80 8.00 8.60];
a=polyfit(x,y,2)
x1=[0.5:0.05:3.0];
y1=a(1)*x1.^2 +a(2)*x1 + a(3);
plot(x,y,’*’,x1,y1,’-r’)
2 利用矩阵除法解决复杂型函数的拟合 例:用最小二乘法求一个形如 y=a+bex 的经 验公式 ,其中 a、 b 为待定参数
x=[0:0.4:2.0];
y=[1.2 1.3 1.45 1.6 2.0 2.5];
x1=exp(x)
x1=[ones(6,1),x1’]
%由 y’=x1ab 得 ab=x1\y’ % 其中 ab=
x2=0:0.01:2.0;
y2=ab(1)+ab(2)*exp(x2);
plot(x,y,’*’,x2,y2,’r’)
a
b
7.1.6 快速 Fourier 变换简介 周期性的连续函数可以用三角多项式逼近。对一组周期性的离散数据,这种逼近用快速 Fourier
变换来实现。设数据列为 x(n), n=1,2,…,N,
它对应的 Fourier 变换为 X(k), k=1,2,…,N
则有 X(k)= ∑ x(n)*exp(-j*2*pi*(k-1)*(n-1)/N)
1<= k <=N
x(n)=(1/N) ∑X(k)*exp(j*2*pi*(k-1)*(n-1)/N)
1<= n <=N
n=1
N
n=1
N
…
命令函数及句法结构: fft(x)
fft(x,n)
fft(x,[],DIM)或 fft(x,n,DIM)
fft2 二维快速离散 Fourier 变换 调用形式 ( 逆函数相同 )
fft2(x)
fft2(x,MROWS,NCOLS)
fftn n 维快速离散 Fourier 变换 调用形式 ( 逆函数相同 )
fftn(x)
fftn(x,siz)
ifft 快速离散 Fourier 逆变换 ifft2 二维快速离散 Fourier 逆变换 ifftn n 维快速离散 Fourier 逆变换例:给出一张记录 {xk }=[4 3 2 1 0 1 2 3],用 FFT
算法求 {xk}, 离散频谱 {Ck }, 其中 k=0,1, …,7.
解 :
>>x=[4 3 2 1 0 1 2 3];
>>fft(x)
卷积运算演示>> x=[4 3 2 1 0 1 2 3];
>> y=[1 1 1 1 1 1 1 1];
>>fx=fft(x,19)
>>fy=fft(y,19)
>>xy=conv(x,y)
>>yx=ifft(fx.*fy)
>>real(yx)
例:见 demo/numerics/fast fourier transform
7.2 积分与微分7.2.1 Newton-Cotes 系列数值求值公式若将积分区间 [a,b] 划分为 n 等份 , 步长 h=(b-a)/n,选取等距节点 xk =a+kh, 构造下面的插值型求公式 .
In =(b-a)
其中 xk =a+kh, Ck(n) 由 Cotes 系数表 7.6 给出 .
当 n=0 时 , 即为矩形公式 ( 稍做变化 )
当 n=1 时 , 即为梯形公式当 n=2 时 , 即为 Simpson 公式当 n=3 时 , 即为 Cotes 公式
sxfC k
n
k
nk )(
0
)(
1 矩形求积公式
y=cumsum(x)
对 n 维向量 x,
返回 n 维向量 y, y(i)是 x 的前 i 个分量之和。 例 :
>>x=[0 1 2;3 4 5];>>cumsum(x,1)>>cumsum(x,2)
2 梯形求积公式 y=trapz(x)
对 n 维向量 x ,返回标量数值 y ,它的值是 x 的
各分量相隔为 1 单位时各小梯形面积之和。
例:求积分 e-0.5t sin(t+/6)dt
解:建立被积函数 function y=fun1(t)
y=exp(-0.5*t).*sin(t+pi/6);
∫0
3π
d=pi/1000; t=0:d:3*pi; nt=length(t); y=fun1(t); sc=cumsum(y)*d; scf=sc(nt) z=trapz(y)*d
3 自适应法-- Simpson 法求积 Q=quad(‘F’,a,b) 求函数 F(x) 从 a到 b 的相对误差为 1e-3 的积分近似值 Q=quad(‘F’,a,b,tol) tol 分别用于指定相对误差和绝对误差 例: ∫ dx
x
x2+4—————
0
1
function f=fun2(x)
f=x./(4+x.^2)
quad(‘fun2’,0,1)
4 自适应法的 Cotes 求积公式 quad8 自适应法的 Cote 求积公式 ( 高阶方法 )
Q=quad8(‘F’,a,b) 使用 Newton-Cotes 法则求自适应递归法求函数 F(X)从 a到 b 的相对误差为 1e-3 的积分近似值 , 其中 F 为函数名 .
Q=quad8(‘F’,a,b,tol)
tol 分别用于指定相对误差和绝对误差
例:求积分 ∫ e - x/2 dx
编制函数文件 :
fun.m
function f=fun(x)
f=exp(-x/2);
>>quad8(‘fun’,1,3,1e-10)
7.2.2 Gauss 求积公式
对任意的求积区间 [a,b], 通过变换 x=(b-
a)x/2+(a+b)/2, 可转化到区间 [-1 , 1] 上。此时
系数为 LegendreGaussA
xfAdxxf
k
n
kkk
0
1
1)()(
dtba
tab
fab
dxxfb
a
1
1)
22(
2)(
例 求下面的积分值
先确定 n 的值。由高斯余项可得下式:
编制函数文件如下: gaussf.m function y=gaussf(x) y=cos(x);>>gauss1(0,1,6)
dxxG 1
0)cos(
6
105270
1
2706
4
5
nn
nh
计算得到
以 n=3 为例 gauss3.m function g=gauss3(fun,a,b,tol) if nargin<4 tol=1e-6;end c=(a+b)/2; x=[a,b,c]; y=feval(fun,x); lev=1; if any(imag(y)) g0=1e30; else
g0=inf; end g=gaussstp1(fun,a,b,tol,lev,g0); function g=gaussstp1(fun,a,b,tol,lev,g0) levmax=10; if lev>levmax disp(‘Reearsion level limit reached in gauss’); g=g0; else c=(a+b)/2; g1=gaussstp2(fun,a,c); g2=gaussstp2(gun,c,b); g=g1+g2; if abs(g-g0)>tol*abs(g)
g1=gaussstp2(fun,a,c,tol/2,lev+1,g1); g2=gaussstp2(fun,c,b,tol/2,lev+1,g2);g=g1+g2; end end function g=gaussstp2(fun,a,b) h=(b-a)/2; c=(a+b)/2; x=[h*(-0.7745967)+c,c,h*0.7745976+c]; f=feaval(fun,x); g=h*(0.555555556*(f(1)+f(3))+0.888888889*f(2));>>gauss3(‘guassf’,0,1)
7.2.3 Romberg 求积公式1 Romberg 加速法
rbgl.m function [s,n]=rbg1(a,b,eps) if nargin<3,eps=1e-6;end s=10; s0=0; k=2; t(1,1)=(b-a)*(f(a)+f(b))/2;
14
4 )(1
)1(1)(
L
kL
kL
Lk
L
TTT
while(abs(s-s0)>eps) h=(b-a)/2^(k-1); w=0; if(h~=0) for i=1:(2^(k-1)-1) w=w+f (a+i*h); end t(k,l)=h*(f(a)/2+w+f(b)/2); for l=2:k for i=1:(k-l+1) t(i,l)=(4^(l-1)*t(i+1,l-1)-t(i,l-1))/(4^(l-1)-1); end end
s=t(1,k);
s0=(t(1,k-1));
k=k+1;
n=k;
else s=s0;
n=-k;
end
end
例 用 Romberg 求积分公式计算积分
dxx2
0
3
解:改编 f.m 函数如下: function f=f(x);
f=x.^3;
计算积分,在 MATLAB 命令窗口中输入:rbg1(0,2)
2 改进 Romberg 的求积函数
rbg2.m
141
111
1
j
kj
kjk
jkj
RRRR
function [s,eer]=rbg2(a,b,eps) if nargin<3, eps=1e-6;end m=1; t(1,1)=(b-a)*(f(a)+f(b))/2; r(1,1)=0; while((abs(t(1,m)-r(1,m))/2)>eps) c=0; for j=1:2^(m-1) c=c+f(a+(j-0.5)*(b-a)/2^(m-1)); end r(m,1)=(b-a)*c/2^(m-1); for j=2:m for k=1(m-j+1)
r(k,j)=r(k+1,j-1)+(r(k+1,j-1)-r(k,j-1))/(4^(j-1)-1);
end
t(l,j)=r(l,j-1)+2*(4^(j-2)-1)*(t(1,j-1)-r(1,j-1))/(4^(j-1)-1);
end
end
err=abs(t(1,m)-r(1,m))/2;
s=t(1,m);
例 计算积分值
dxxx 3
0
21
解:被积分的 M 文件 f.m 变为 :
function f=f(x)
f=x.*sqrt(1+x.^2);
计算积分,在 MATLAB 命令窗口中输入:>>rbg1(0,3)
7.2.4 Mote-Carlo 方法简介(积分多维)求解半球体积设半球体积为: f(x,y,z)=
其中3222 zyx
33
33
y
x
由于是半球,因此,编制 Mote-Carlo 函数 mtc1.m
function y=mtc1(fun,x,y,z,n)
if nargin<5 n=1000;end
n0=0;
xh=x(2)-x(1);
yh=y(2)-y(1);
zh=z(2)-z(1);
for i=1
a=xh*rand+x(1)
b=yh*rand+y(1)
c=zh*rand+z(1)
30 z
f=feval(fun,a,b,c);
if f<=0
n0=n0+1;
end
end
y=n0/n*xh*yh*zh
球函数f.m
function f=f(x,y,z);
f=x.^2+ y.^2+ z.^2-3;
积分计算:
>>x=[-sqrt(3),sqrt(3)]>>y=[-sqrt(3),sqrt(3)]>>z=[0,sqrt(3)];>>mtc1(‘f’,x,y,z,) 当增加随机点的个数时 mtc1(‘f’,x,y,z,1000)
7.2.6 微分和差分1 数值微分和差分 diff(x) 对向量 x , 其值为 [ x(2)-x(1) x(3)-x(2)
… x(n)-x(n-1)] diff(X) 对矩阵 X ,其值为矩阵列的差分
[X(2: n,:)-X(1:n-1,:)]
diff(X,n) 求 n 阶的差分值,如果 n size(X,DIM),diff 函数将先计算可能的连续差分值,直到
size(X,DIM)=1. 然后 diff 沿任意 n+1 维进行差分计算
diff(X,n,DIM) 求 n 阶的差分值,如果 n size(X,DIM), 函数返回空数组
2 符号微分和差分 diff(S) 对由 findsym 返回的自变量微分符号表达式 S
diff(S ’, V’) 或 diff(S, sym’V’) 对自变量 v 微分符号表达式 S
diff(S, n) 对正整数 n ,函数微分 S 表达式 n 次diff(S,n,’V’) 和 diff(S,’V’ , n )两种形式都可以被
识别
例 x=sym(‘x’);
diff(sin(x^2))
3 梯度函数 gradient 近似梯度函数[fx,fy]=gradient(F) 返回矩阵 F 的数值梯度, fx
相当于 dF/dx, 为 x 方向的差分值。 fy 相当于 dF/dx,为 y 方向的差分值。各个方向的点间隔设为 1 。当 F 为向量分值, DF=gradient(F) 为一维梯度
7.3 求一元高次方程与线性方程组 an xn+an-1 xn-1+…+a0=0
p=[an , an-1 , … ,a0 ]
x0=roots(p)
n 元线性方程组可表达为 AX= b % A为 nxn 阶系数矩阵 % b为 nx1 阶常数矩阵 % X为 nx1 阶变量矩阵 X= A\b
例 求解下列方程组
2557.03927.02786.04002.01784.0
4240.00643.03781.01920.03645.0
1550.01129.04015.03872.02246.0
4043.02943.03678.01234.04096.0
4321
4321
4321
4321
xxxx
xxxx
xxxx
xxxx
解:在 MATLAB 命令窗中输入: a=[0.4096 0.1234 0.3678 0.2943 0.2246 0.3872 0.4015 0.1129 0.3645 0.1920 0.3781 0.0643 0.1784 0.4002 0.2786 0.3927]; b=[0.4043 0.1550 0.4240 –0.2557]’; x=a\b
7.3.2 迭代解法的几种形式1 Jacobi 迭代法方程组 Ax=b, 其中 A ∈ , b , ∈ 且 A 为非奇异,则 A 可写成 A=D-L-U 。其中, D=
diag , 而 -L、 -U 分别为 A 的严格下三角部分(不包括对角线元素)
则
nnR nR
],,,[ 2211 nnaaa
bDfADIULDB
fBxx
bDxULDxkk
111
)()1(
11 ,)(
,)(其中:
可构造迭代法:
由此
2 Gauss-Seidel(G-S) 迭代法
3. SOR 迭代法4. 两步迭代法 当线性方程系数矩阵为对称正定时,可用一种特殊的迭代法来解决,其迭代公式如下:
bLxxUD
bUxxLD
kk
kk
)2
1(1
)(2
1
)(
)(
MATLAB 的实现 jacobi.mD=diag(diag(a));U=-triu(a,-1);L=-triu(a,-1);B=D\(L+U); f=D\b; y=B*x0+f;n=1; while norm(y-x0)>1.0e-6 x0=y; y =B*x0+f;n=n+1; end y n
例 用 Jacobi 方法求解方程组 ,设 x(0)=0, 精度为
a=[10 –1 0;-1 10 –2 10];
b=[9;7;6];
jacobi(a,b,[0;0;0])
例:对上例的方程组,以 Gauss-Seidel 方法求解。 seidel(a,b,[0;0;0])
6102
7210
910
32
321
21
xx
xxx
xx.10 6
例 在上述例 中,当 =1.103 时,用 SOR 法求截原方程
a=[10 –1 0;-1 10 –2 10];
b=[9;7;6];
sor(a,b,1.103,[0;0;0])
7.3.3 线性方程组的符号解法例 还上述的方程组为例,用符号求解函数来求解。a=sym(‘[10 –1 0;-1 10 –2 10]’);
b=(‘[9;7;6]’);
linsolve(a,b)
vpa(ans)
7.4 求解非线性方程7.41 二分法 对函数 f(x), 在区间 [a,b], 若有 f(a)*f(b)<0, 则在该区间内至少有一个根。求解命令: erfen(‘fun’,a,b,tol)例:用二分法求方程 x2-x-1=0 的正根,要求误差小 于 0.05 。 fun4.m function y=fun4(x) y=x^2-x-1; x=-4:0.01:4; plot(x,0,’r’,x,x.*x-x-1) erfen(‘fun4’,0,10,0.05)
7.4.2 Newton 迭代法 迭代公式 xk+1=xk- —————
编制 m 函数 newton.m
求 3x2 – ex = 0
解: fc.m
function y=fc(x)
y=3*x.^2-exp(x);
fd.m
function y=df(x)
f (xk)
f ’ (xk)
y=6*x-exp(x);
x=-1:0.01:4
plot(x,0,’r’,x,3*x.^2-exp(x))
newton(0)
newton(1)
newton(3.5)
7.6 常微分方程的求解 常用的微分方程的数值求解方法有欧拉法和Runge-Kutta 法。在 MATLAB 中,使用 Runge-
Kutta 法,针对不同性质的微分方程已编制出微分
方程的系列求解命令函数 ODE, 包括 ode23,ode45,ode113,ode15s,ode23s. ode 命令函数使用说明(以 ode45 为例) 将微分方程(组)表示为 y ’ = f ( t , y ) %注意:方程是矢量形式 则微分方程的解为 [T,Y]=ode45(‘fun’,Tspan,Y0) 其中 T 为一个列矢量,每一个元素对应一个时刻, Y 为与 T 有相同行数的矩阵,其列数与微分方程 组中未知函数的个数相同,每一行为各个求解函 数在对应时刻的函数值。 fun 为描写微分方程组的 m 函数名。
Tspan=[T0 TFINAL] 是微分方程的求解区间 Y0 是微分方程初始条件,用矩阵形式给出。 例:解常微分方程的初值问题 y’’-3(1-y2)y’+y=0
y(0)=2, y’(0)=3
解:设 y1=y, y2 =y’ 原式可化为标准形式: y1’=y2
y2’=3(1-y12)y2-y1
把微分方程组编成 M 文件 function dy=F(t,y)
dy=[y(2);3*(1-y(1)^2)*y(2)-y(1)];
%注意: y=[y1; y2] dy=[y1’ ; y2’]
初始条件写为 Y0=[2 ; 3]
满足初值条件 y1(0)=2
y2(0)=3
%注意: dy 必须为列向量,函数文件必须包
含 t , y 两个输入变量 [T,Y]=ode23(‘F’,[0 50],[2;3])
%注意: T0=0, TFINAL=50
为观察解的图像,可以使用以下两种方法: ode23(‘F’,[0 50],[2;3])
或 plot(T,Y(:,1),T,Y(:,2))