關於MATLAB實現以及C語言實現離散傅里葉變換(DFT)——傅里葉變換的學習與認識(下)
3.離散傅里葉變換(DFT)
離散傅里葉變換指的是傅里葉變換在時域和頻域上都呈離散的形式。在形式上,時域和頻域上的序列都是有限長的,而實際上這兩組序列都應當被認爲是離散週期信號的主值序列。對於有限長的離散信號作DFT,可以把它看作是離散週期信號的一個週期,應進行週期延拓之後再進行計算。
3.1 用C語言實現DFT
設有限長序列的長度爲N,對應的離散傅里葉變換定義爲:
我們用C語言實現DFT計算,實際就是求f(n)的值,也就是求信號的幅值。
根據歐拉公式
在c語言中複數由實部和虛部組成,代入DFT的計算式可以得到:
實現代碼
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#define PI 3.14159
struct data
{
double real,imag;
};
int main()
{
int N=32; //序列長度
double Squence[100]; //序列
double Amplitude[100]; //幅值
struct data one[32]; //單個數據
struct data sum; //求和的結果
int n;
int k; //表示第k個數
//產生一個長度爲N的序列 第k個數的值爲k
for(k=0;k<N;k++)
{
Squence[k]=k;
}
//進行DFT計算,並輸出結果
for(k=0;k<N;k++)
{
//對sum賦初值
sum.real=0;
sum.imag=0;
//計算第k個點處的幅值
for(n=0;n<N;n++)
{
one[n].real = cos(2*PI/N*k*n)*Squence[n]; //實部
one[n].imag = -sin(2*PI/N*k*n)*Squence[n]; //虛部
sum.real += one[n].real; //實部求和
sum.imag += one[n].imag; //虛部求和
}
Amplitude[k] = sqrt(sum.real*sum.real+sum.imag*sum.imag); //計算幅值 sqrt(a^2+b^2)
printf("%d \t%f\n",k,Amplitude[k]); //輸出計算結果
}
return 0;
}
調用tcc與gnuplot編譯與做圖
在DFT.c的路徑下
tcc DFT.c //將源文件編譯生成爲可執行文件DFT.exe
DFT.exe > DFT.txt //通過重定向的方法,將執行結果產生的數據重新放到一個新的文件中
gnuplot //調用畫圖工具
plot[0:32] [0:120] "DFT.txt" u 1:2 w p //作出該信號的離散傅里葉變換的點狀圖
運行結果
3.2 MATLAB實現DFT
實現代碼
%計算長度爲32點的DFT
N=32;%信號的長度
x=[1:N];%定義存放信號的數組
a=zeros(1,N);b=zeros(1,N);%構造長度爲N的序列
for k=0:N-1
for i=0:N-1
a(k+1)=a(k+1)+x(i+1)*cos(2*pi*k*i/N);%DFT公式
b(k+1)=b(k+1)+x(i+1)*sin(2*pi*k*i/N);
end
c(k+1)=sqrt(a(k+1)^2+b(k+1)^2);%算出幅值
end
f=(0:1:N-1);
plot(f,c,'r'); %畫圖
axis([0 32 0 120]);
title('DFT');xlabel('k');ylabel('x(k)');
運行結果
3.3 結果對比
發現整體誤差較小