MATLAB 之 数值积分和离散傅里叶变换

一、数值积分

  • 数值积分时研究定积分的数值求解方法,即借助于计算机,用数值逼近的方法近似计算定积分。

1. 数值积分基本原理

  • 我们假设 I 1 = ∫ a b f ( x ) d x I_{1}=\int_{a}^{b}f(x)\mathrm{d}x I1=abf(x)dx I 2 = ∫ a b p ( x ) d x I_{2}=\int_{a}^{b}p(x)\mathrm{d}x I2=abp(x)dx
  • 从高等数学中知道,当 ∣ f ( x ) p ( x ) ∣ < e |f(x)p(x)|<e f(x)p(x)<e 时, ∣ I 1 − I 2 ∣ < ε ( b − a ) \left | I_{1}-I_{2} \right | <\varepsilon (b-a) I1I2<ε(ba)。这说明,当 ε \varepsilon ε 充分小时,可用 I 2 I_{2} I2 近似地代替 I 1 I_{1} I1
  • 所以,求任意函数 f ( x ) f(x) f(x) [ a , b ] [a, b] [a,b] 上的定积分时,要是难以使用解析的方法求出 f ( x ) f(x) f(x) 的原函数,则可以寻找一个在 [ a , b ] [a, b] [a,b] 上与 f ( x ) f(x) f(x) 逼近,但形式上却简单且易于求积分的函数 p ( x ) p(x) p(x),用 p ( x ) p(x) p(x) [ a , b ] [a, b] [a,b] 上的积分值近似地代替 f ( x ) f(x) f(x) [ a , b ] [a, b] [a,b] 上的积分值。
  • 一般选择被积函数的插值多项式充当这样的替代函数。选择的插值多项式的次数不同,就形成了不同的数值积分公式。选择一次多项式时,称为梯形公式,选择二次多项式时,称为辛普森(Simpson)公式。
  • 如果把积分区间 [ a , b ] [a, b] [a,b] 分划为 n n n 个等长的子区间: [ a , b ] = [ a , a 1 ] ∪ [ a 1 , a 2 ] ∪ ⋯ ∪ [ a n − 1 , b ] [a,b]=[a,a_{1}]\cup [a_{1},a_{2}]\cup \dots \cup [a_{n-1},b] [a,b]=[a,a1][a1,a2][an1,b]
  • 则在每个子区间 [ a i , a i + 1 ] [a_{i}, a_{i+1}] [ai,ai+1] 上用 f ( x ) f(x) f(x) 的插值多项式 p ( x ) p(x) p(x) 代替 f ( x ) f(x) f(x),其逼近效果一般会比在整个区间上使用一个统一的插值多项式时更好。这样就形成了数值积分负荷公式。对被积函数 f ( x ) f(x) f(x) 采用一、二次多项式插值,然后对插值多项式求积分,就得到了几个常见的数值积分公式: S 1 = b − a 2 [ f ( a ) + f ( b ) ] S_{1}=\frac{b-a}{2}[f(a)+f(b)] S1=2ba[f(a)+f(b)] S 2 = b − a 6 [ f ( a ) + 4 f ( a + b 2 ) + f ( b ) ] S_{2}=\frac{b-a}{6}[f(a)+4f(\frac{a+b}{2})+f(b)] S2=6ba[f(a)+4f(2a+b)+f(b)] S 3 = h 2 [ f ( a ) + f ( b ) + 2 ∑ i = 1 n − 1 f ( a + i h ) ] S_{3}=\frac{h}{2}[f(a)+f(b)+2\sum_{i=1}^{n-1}f(a+ih)] S3=2h[f(a)+f(b)+2i=1n1f(a+ih)] S 4 = h 6 [ f ( a + i h ) + 4 f ( a + i + 1 2 h ) + f ( a + ( i + 1 ) h ) ] S_{4}=\frac{h}{6}[f(a+ih)+4f(a+\frac{i+1}{2}h)+f(a+(i+1)h)] S4=6h[f(a+ih)+4f(a+2i+1h)+f(a+(i+1)h)]

2. 数值积分的实现

2.1 变步长辛普森法

  • 基于变步长辛普森法,MATLAB 给出了 quad 函数和 quadl 函数来求定积分。函数的调用格式如下:
	[I,n]=quad(filename,a,b,tol,trace)
	[I,n]=quadl(filename,a,b,tol,trace)
  • 其中,filename 是被积函数名;a 和 b 分别是定积分的下限和上限,积分限 [a, b] 必须是有限的,不能为无穷大(Inf);tol 用来控制积分精度,默认时取 tol= 1 0 − 6 10^{-6} 106;trace 控制是否展现积分过程,若取非 0 则展现积分过程,取 0 则不展现,默认时取 trace=0;返回参数 I 即定积分值,n 为被积函数的调用次数。
  • 例如,我们求 I = ∫ 0 1 e − x 2 d x I=\int_{0}^{1}e^{-x^{2}}\mathrm{d}x I=01ex2dx
  • 对此,先建立一个函数文件 fex.m。
	function f=fex(x)
	f=exp(-x.^2)
	end
  • 在建立被积函数的函数文件时,因为函数文件允许向量作为输入参数,所以在函数表达式中要采用点运算符。
  • 接下来,我们调用积分函数 quad 求定积分,程序如下:
>> [I,n]=quad(@fex,0,1)

I =

    0.7468


n =

    13

  • 也可不建立关于被积函数的函数文件,而使用匿名函数(或内联函数)求解,程序如下:
>> f=@(x) exp(-x.^2);	%使用匿名函数f(x)定义被积函数
>> [I,n]=quad(f,0,1)	%注意函数句柄f前面不用加@号

I =

    0.7468


n =

    13

  • 例如,我们分别用 quad 函数和 quadl 函数求 I = ∫ 0 1 4 1 + x 2 d x I=\int_{0}^{1}\frac{4}{1+x^{2}} \mathrm{d}x I=011+x24dx 的近似值,并在相同的积分精度下,比较函数的调用次数。
  • 程序如下:
>> format long
>> f=@(x) 4./(1+x.^2);
>> [I,n]=quad(f,0,1,1e-8)	%调用函数quad求定积分

I =

   3.141592653733437


n =

    61

>> [I,n]=quadl(f,0,1,1e-8)	%调用函数quadl求定积分

I =

   3.141592653589806


n =

    48

>> (atan(1)-atan(0))*4	%理论值

ans =

   3.141592653589793

>> format

  • 当精度取 1 0 − 8 10^{-8} 108 时,quad 函数调用被积函数的次数是 61 次,quadl 函数调用被积函数的次数是 48 次,因而此时后者效率要明显高于前者,而且精度也更高。

2.2 自适应积分法

  • MATLAB 提供了基于全局自适应积分算法的 integral 函数来求定积分,函数的调用格式如下:
	I=integral (filename,a,b)
  • 其中,I 是计算得到的积分;filename 是被积函数,它必须是函数句柄;a 和 b 分别是定积分的下限和上限,积分限可以为无穷大。
  • 例如,我们求 I = ∫ 1 e 1 x 1 − ln ⁡ 2 x d x I=\int_{1}^{e}\frac{1}{x\sqrt{1-\ln_{}^{2}{x}}} \mathrm{d}x I=1ex1ln2x 1dx
  • 先建立被积函数文件 fe.m。
function f = fe(x)
f=1./(x.*sqrt(1-log(x).^2));
end
  • 再调用数值积分函数 integral 求定积分,程序如下:
 >> I=integral(@fe,1,exp(1))

I =

    1.5708

2.3 高斯——克朗罗德法

  • MATLAB 提供了基于自适应高斯——克朗罗德法的 quadgk 函数来求振荡函数的定积分。该函数的调用格式如下:
	[I,err]=quadgk(filename,a,b)
  • 其中,err 返回近似误差范围,其他参数的含和用法与 quad 函数相同。积分上下限可以是 -Inf 或 Inf,也可以是复数。如果积分上下限是复数,则 quadgk 在复平面上求积分。
  • 例如,我们求 ∫ 2 π + ∞ 1 x 2 sin ⁡ 1 x d x \int_{\frac{2}{\pi}}^{\frac{}{} +\infty}\frac{1}{x^{2}}\sin \frac{1}{x}\mathrm{d}x π2+x21sinx1dx
  • 先建立被积函数文件 fsx.m。
function f = fsx(x)
f=sin(1./x)./x.^2;
end
  • 再调用数值积分函数 quadgk 求定积分,程序如下:
 >> I=quadgk(@fsx,2/pi,+Inf)

I =

    1.0000

2.4 梯形积分法

  • 在科学实验和工程应用中,函数关系表达式往往是不知道的,只有实验测定的一组样本点和样本值,这时,就无法使用 quad 等函数计算定积分。
  • 在 MATLAB 中,对由表格形式定义的函数关系的求定积分问题用梯形积分函数 trapz,其调用格式如下:
	I=trapz(X,Y)
  • 其中,向量 X 、 Y X、Y XY 定义函数关系 Y = f ( X ) Y=f(X) Y=f(X) X 、 Y X、Y XY 是两个等长的向量: X = ( x 1 , x 2 , … , x n ) X=(x_{1},x_{2},…,x_{n}) X=(x1,x2,,xn) Y = ( y 1 , y 2 , … , y n ) Y=(y_{1},y_{2},…,y_{n}) Y=(y1,y2,,yn),并且 x 1 < x 2 < … < x n x_{1}< x_{2}<…<x_{n} x1<x2<<xn,积分区间是 [ x 1 , x n ] [x_{1},x_{n}] [x1,xn]
  • 例如,我们用 trapz 函数计算定积分 ∫ 0 1 4 1 + x 2 d x \int_{0}^{1} \frac{4}{1+x^{2}}\mathrm{d}x 011+x24dx
  • 程序如下:
>> format long
>> x=0:0.001:1;
>> y=4./(1+x.^2);	%生成函数向量
>> trapz(x,y)

ans =

   3.141592486923126

>> format

2.5 累计梯形积分

  • 在 MATLAB 中,提供了对数据积分逐步累计的函数 cumtrapz。该函数调用格式如下:
	Z=cumtrapz(Y)
	Z=cumtrapz(X,Y)
  • 对于向量 Y Y Y Z Z Z 是一个与 Y Y Y 等长的向量;对于矩阵 Y Y Y Z Z Z 是一个与 Y Y Y 相同大小的矩阵,累计计算 Y Y Y 每列的积分。函数其他参数的含义和用法与 trapz 函数的相同。例如:
>> S=cumtrapz([1:5;2:6]')

S =

         0         0
    1.5000    2.5000
    4.0000    6.0000
    7.5000   10.5000
   12.0000   16.0000

3. 多重定积分的数值求解

  • 定积分的被积函数是一元函数, 积分范围是一个区间, 而重积分的被积函数是二元函数或三元函数,积分范围是平面上的一个区域或空间中的一一个区域。
  • MATLAB 提供的 integral2quad2ddblquad 函数用于求 ∫ c d ∫ a b f ( x , y ) d x d y \int_{c}^{d}\int_{a}^{b}f(x,y)\mathrm{d}x \mathrm{d}y cdabf(x,y)dxdy 的数值解,integral3triplequad 函数用于求 ∫ f e ∫ c d ∫ a b f ( x , y , z ) d x d y d z \int_{f}^{e}\int_{c}^{d}\int_{a}^{b}f(x,y,z)\mathrm{d}x\mathrm{d}y\mathrm{d}z fecdabf(x,y,z)dxdydz 的数值解。函数的调用格式如下:
	I=integral2(filename,a,b,c,d)
	I=quad2d(filename,a,b,c,d)
	I=dblquad(filename,a,b,c,d, tol)
	
	I=integral3(filename,a,b,c,d,e,f)
	I=triplequad(filename,a,b,c,d,e,f, tol)
  • 其中,I 返回积分值;filename 为被积函数; [ a , b ] [a, b] [a,b] 为 x 的积分区域, [ c , d ] [c, d] [c,d] 为 y 的积分区域, [ e , f ] [e, f] [e,f] 为 z 的积分区域;dblquad 函数和 triplequad 函数中参数 tol 的用法与 quad 函数相同。
  • 这里需要注意的是,这些函数不允许返回被积函数的调用次数,如果需要,可以在被积函数中设置一个记数变量,从而统计出被积函数的调用次数。
  • 例如,我们计算二重积分 ∫ − 1 1 ∫ − 2 2 e − x 2 / 2 sin ⁡ ( x 2 + y ) d x d y \int_{-1}^{1}\int_{-2}^{2}e^{-x^{2}/2}\sin (x^{2}+y)\mathrm{d}x\mathrm{d}y 1122ex2/2sin(x2+y)dxdy
  • 首先,建立一个函数文件 fxy.m。
function f = fxy(x,y)
global ki;
ki=ki+1;	%ki用于统计被积函数的调用次数
f=exp(-x.^2/2).*sin(x.^2+y);
end
  • 然后,我们调用函数求解,程序如下:
>> global ki;
>> ki=0;
>> I=integral2(@fxy,-2,2,-1,1)		%调用integral2函数求解

I =

    1.5745

>> ki

ki =

    22

>> ki=0;
>> I=quad2d(@fxy,-2,2,-1,1)		%调用quad2d函数求解

I =

    1.5745

>> ki

ki =

    20
    
>> ki=0;
>> I=dblquad(@fxy,-2,2,-1,1)	%调用dblquad函数求解

I =

    1.5745

>> ki

ki =

        1050

  • 例如,我们计算三重积分 ∫ 0 1 ∫ 0 π ∫ 0 π 4 x z e − z 2 y − x 2 d x d y d z \int_{0}^{1}\int_{0}^{\pi}\int_{0}^{\pi}4xze^{-z^{2}y-x^{2}}\mathrm{d}x\mathrm{d}y\mathrm{d}z 010π0π4xzez2yx2dxdydz
  • 程序如下:
>> fxyz=@(x,y,z) 4*x.*z.*exp(-z.*z.*y-x.*x);	%定义被积函数
>> integral3(fxyz,0,pi,0,pi,0,1)				%调用integral3函数求解

ans =

    1.7328

>> triplequad(fxyz,0,pi,0,pi,0,1,1e-7)			%调用triplequad函数求解

ans =

    1.7328

二、离散傅里叶变换

  • 离散傅里叶变化(DFT)广泛应用于信号分析、光谱和声谱分析、全息技术等领域,但直接计算 DFT 的运算量与变换的长度 N N N 的平方成正比,当 N N N 较大时,计算量太大。
  • 随着计算机技术的迅速发展,在计算机上进行离散傅里叶变换计算成为可能,特别是快速傅里叶变换(FTT)算法的出现,为离散傅里叶变换的应用创造了条件。
  • MATLAB 提供了一套计算快速傅里叶变换的函数,它们包括求一维、二维和 N N N 维离散傅里叶变换函数 fft、fft2 和 fftn,还包括求上述各维离散傅里叶变换的逆变换函数 ifft、ifft2 和 ifftn 等。

1. 离散傅里叶变换算法简介

  • 在某时间片等距地抽取 N N N 个抽样时间 t m t_{m} tm 处的样本值 f ( t m ) f(t_{m}) f(tm),且记作 f ( m ) f(m) f(m),这里 m = 0 , 1 , 2 , … , N − 1 m=0,1,2,…,N-1 m=0,1,2,,N1,称向量 F ( k ) ( k = 0 , 1 , 2 , … , N − 1 ) F(k)(k=0,1,2,…,N-1) F(k)k=0,1,2,,N1 f ( m ) f(m) f(m) 的一个离散傅里叶变换,其中 F ( k ) = ∑ m = 0 N f ( m ) e − j 2 π m k / N , k = 0 , 1 , 2 , … , N F(k)=\sum_{m=0}^{N}f(m)e^{-j2\pi mk/N},k=0,1,2,…,N F(k)=m=0Nf(m)ej2πmk/N,k=0,1,2,,N
  • 因为 MATLAB 不允许有零下标,所以将上述公式中 m m m 的下标均移动 1,于是便得到相应公式: F ( k ) = ∑ m = 1 N f ( m ) e − j 2 π ( m − 1 ) ( k − 1 ) / N , k = 1 , 2 , … , N F(k)=\sum_{m=1}^{N}f(m)e^{-j2\pi (m-1)(k-1)/N},k=1,2,…,N F(k)=m=1Nf(m)ej2π(m1)(k1)/N,k=1,2,,N
  • f ( m ) f(m) f(m) F ( k ) F(k) F(k) 的过程,称为求 f ( m ) f(m) f(m) 的傅里叶变换,又称 F ( k ) F(k) F(k) f ( m ) f(m) f(m) 的离散频谱。反之,由 F ( k ) F(k) F(k) 逆求 f ( m ) f(m) f(m) 的过程,称为离散傅里叶逆变换,相应的变换公式为: f ( m ) = 1 N ∑ k = 1 N F ( k ) e j 2 π ( m − 1 ) ( k − 1 ) / N , m = 1 , 2 , … , N f(m)=\frac{1}{N}\sum_{k=1}^{N}F(k)e^{j2\pi (m-1)(k-1)/N},m=1,2,…,N f(m)=N1k=1NF(k)ej2π(m1)(k1)/N,m=1,2,,N

2. 离散傅里叶变换的实现

  • MATLAB 提供了对向量或直接对矩阵进行傅里叶变换的函数。其中,一维离散傅里叶变换函数,其调用格式如下。
  • (1) fft(X):返回向量 X X X 的离散傅里叶变化。设 X X X 的长度(即元素个数)为 N N N,若 N N N为 2 的幂次,则为以 2 为基数的快速傅里叶变换,否则为运算速度很慢的非 2 幂次的算法。对于矩阵 X X X,fft(X) 应用于矩阵的每一列。
  • (2) fft(X,N):计算 N N N 点离散傅里叶变换。它限定向量的长度为 N N N,若 X X X 的长度小于 N N N,则不足部分补上零;若大于 N N N,则删去超出 N N N 的那些元素。对于矩阵 X X X,它同样应用于矩阵的每一列,只是限定了每一列的长度为 N N N
  • (3) fft(X,[],dim)fft(X,N,dim):这是对于矩阵而言的函数调用格式,前者的功能与 fft(X) 基本相同,而后者则与 fft(X,N) 基本相同。只是当参数 dim=1 时,该函数作用于 X X X 的每一列;当 dim=2 时,则作用于 X X X 的每一行。
  • 值得一提的是,当已知给出的样本数 N 0 N_{0} N0 不是 2 的幂次时,可以取一个 N N N 使它大于 N 0 N_{0} N0 且是 2 的幂次,然后利用函数格式 fft(X,N)fft(X,N,dim) 便可进行快速傅里叶变换。这样,计算速度将大大加快。
  • 相应地,一维离散傅里叶逆变换函数是 ifftiff(F) 返回 F F F 的一维离散傅里叶逆变换;iff(F,N) N N N 点逆变换;ifft(F,[],dim)ifft(F,N,dim) 则由 N N N 或 dim 确定逆变换的点数或操作方向。
  • 例如,给定数学函数 x ( t ) = 12 sin ⁡ ( 2 π × 10 t + π / 4 ) + 5 cos ⁡ ( 2 π × 40 t ) x(t)=12\sin (2\pi ×10t+\pi /4)+5\cos (2\pi ×40t) x(t)=12sin(2π×10t+π/4)+5cos(2π×40t)我们取 N = 128 N=128 N=128,试对 t t t 0 ∼ 1 0\sim1 01 采样,用 fft 函数作快速傅里叶变换,绘制相应的振幅——频率图。
  • 0 ∼ 1 0\sim1 01 s 时间范围内采样 128 点,从而可以确定采样周期和采样频率。由于离散傅里叶变化时下标是从 0 到 N − 1 N-1 N1,故我们在实际应用时下标应该向前移动 1。又考虑到对离散傅里叶变换来说,其振幅 ∣ F ( k ) ∣ \left | F(k) \right | F(k) 是关于 N / 2 N/2 N/2 对称的,故只需使 k k k 0 ∼ N / 2 0\sim N/2 0N/2 即可。
  • 程序如下:
N=128;											%采样点数
T=1;											%采样时间终点
t=linspace(0,T,N);								%给出N个采样时间
x=12*sin(2*pi*10*t+pi/4)+5*cos(2*pi*40*t);		%求各采样点样本值x .
dt=t(2)-t(1);									%采样周期
f=1/dt;											%采样频率(Hz)
X=fft(x);										%计算x的快速傅里叶变换X
F=X(1:N/2+1);									%F(k)=X(k) (k=1:N/2+1)
f=f*(0:N/2)/N;									%使频率轴f从零开始
plot(f,abs(F),'-*')								%绘制振幅-频率图
xlabel('Frequency');
ylabel('|F(k)|');
  • 运行程序所绘制的振幅——频率如下图所示。从下图可以看出,在幅值曲线上有两个峰值点,对应的频率为 10 H z 10Hz 10Hz 40 H z 40Hz 40Hz,这正是给定函数中的两个频率值。

在这里插入图片描述

  • X X X 的快速傅里叶逆变换,并与原函数进行比较,程序如下:
>> ix=real(ifft(X));		%求逆变换,结果只取实部
>> plot(t,x,'-*',t,ix,':')	%逆变换结果和原函数的曲线
>> norm(x-ix)				%逆变换结果和原函数之间的距离

ans =

   3.1954e-14

  • 逆变换结果和原函数曲线如下图所示,可以看出两者一致。另外,逆变换结果和原函数之间的距离也很接近。

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_45891612/article/details/131075959