怎么用C语言实现FFT算法 呀
float ar[1024],ai[1024];/* 原始数据实部,虚部 */float a[2050];void fft(int nn) /* nn数据长度 */{ int n1,n2,i,j,k,l,m,s,l1; float t1,t2,x,y; float w1,w2,u1,u2,z; float fsin[10]={0.000000,1.000000,0.707107,0.3826834,0.1950903,0.09801713,0.04906767,0.02454123,0.01227154,0.00613588,}; float fcos[10]={-1.000000,0.000000,0.7071068,0.9238796,0.9807853,0.99518472,0.99879545,0.9996988,0.9999247,0.9999812,}; switch(nn) { case 1024: s=10; break; case 512: s=9; break; case 256: s=8; break; } n1=nn/2; n2=nn-1; j=1; for(i=1;i<=nn;i++) {a[2*i]=ar[i-1];a[2*i+1]=ai[i-1]; } for(l=1;l<n2;l++) { if(l<j) {t1=a[2*j];t2=a[2*j+1];a[2*j]=a[2*l];a[2*j+1]=a[2*l+1];a[2*l]=t1;a[2*l+1]=t2; } k=n1; while (k<j) {j=j-k;k=k/2; } j=j+k; } for(i=1;i<=s;i++) {u1=1;u2=0;m=(1<<i);k=m>>1;w1=fcos[i-1];w2=-fsin[i-1];for(j=1;j<=k;j++){ for(l=j;l<nn;l=l+m) {l1=l+k;t1=a[2*l1]*u1-a[2*l1+1]*u2;t2=a[2*l1]*u2+a[2*l1+1]*u1;a[2*l1]=a[2*l]-t1;a[2*l1+1]=a[2*l+1]-t2;a[2*l]=a[2*l]+t1;a[2*l+1]=a[2*l+1]+t2; } z=u1*w1-u2*w2; u2=u1*w2+u2*w1; u1=z;} } for(i=1;i<=nn/2;i++) {ar[i]=4*a[2*i+2]/nn; /* 实部 */ai[i]=-4*a[2*i+3]/nn; /* 虚部 */a[i]=4*sqrt(ar[i]*ar[i]+ai[i]*ai[i]); /* 幅值 */ }}(http://zhidao.baidu.com/question/284943905.html?an=0&si=2)
如何用C语言实现RSA算法?
上学期交的作业,已通过老师在运行时间上的测试
#include
#include
unsigned long prime1,prime2,ee;
unsigned long *kzojld(unsigned long p,unsigned long q) //扩展欧几里得算法求模逆
{
unsigned long i=0,a=1,b=0,c=0,d=1,temp,mid,ni[2];
mid=p;
while(mid!=1)
{
while(p>q)
{p=p-q;mid=p;i++;}
a=c*(-1)*i+a;b=d*(-1)*i+b;
temp=a;a=c;c=temp;
temp=b;b=d;d=temp;
temp=p;p=q;q=temp;
i=0;
}
ni[0]=c;ni[1]=d;
return(ni);
}
unsigned long momi(unsigned long a,unsigned long b,unsigned long p) //模幂算法
{
unsigned long c;
c=1;
if(a>p) a=a%p;
if(b>p) b=b%(p-1);
while(b!=0)
{
while(b%2==0)
{
b=b/2;
a=(a*a)%p;
}
b=b-1;
c=(a*c)%p;
}
return(c);
}
void RSAjiami() //RSA加密函数
{
unsigned long c1,c2;
unsigned long m,n,c;
n=prime1*prime2;
system("cls");
printf("Please input the message:\n");
scanf("%lu",&m);getchar();
c=momi(m,ee,n);
printf("The cipher is:%lu",c);
return;
}
void RSAjiemi() //RSA解密函数
{
unsigned long m1,m2,e,d,*ni;
unsigned long c,n,m,o;
o=(prime1-1)*(prime2-1);
n=prime1*prime2;
system("cls");
printf("Please input the cipher:\n");
scanf("%lu",&c);getchar();
ni=kzojld(ee,o);
d=ni[0];
m=momi(c,d,n);
printf("The original message is:%lu",m);
return;
}
void main()
{unsigned long m;
char cho;
printf("Please input the two prime you want to use:\n");
printf("P=");scanf("%lu",&prime1);getchar();
printf("Q=");scanf("%lu",&prime2);getchar();
printf("E=");scanf("%lu",&ee);getchar();
if(prime1<prime2)
{m=prime1;prime1=prime2;prime2=m;}
while(1)
{
system("cls");
printf("\t*******RSA密码系统*******\n");
printf("Please select what do you want to do:\n");
printf("1.Encrpt.\n");
printf("2.Decrpt.\n");
printf("3.Exit.\n");
printf("Your choice:");
scanf("%c",&cho);getchar();
switch(cho)
{case '1':RSAjiami();break;
case '2':RSAjiemi();break;
case '3':exit(0);
default:printf("Error input.\n");break;
}
getchar();
}
}
求用C语言实现FFT变换的程序(见下面)
你好,这是我的回答,希望可以帮到你。
1)结果讨论
一,如果对信号进行同样点数N的FFT变换,采样频率fs越高,则可以分析越高频的信号;与此同时,采样频率越低,对于低频信号的频谱分辨率则越好。
二,假设采样点不在正弦信号的波峰、波谷、以及0电压处,频谱则会产生泄露(leakage)。
三,对于同样的采样率fs,提高FFT的点数N,则可提高频谱的分辨率。
四,如果采样频率fs小于2倍信号频率2*fs(奈圭斯特定理),则频谱分析结果会出错。
五,对于(二)中泄露现象,可以通过在信号后面补零点解决。
2)程序及注解如下
%清除命令窗口及变量
clc;
clear all;
%输入f、N、T、是否补零(补几个零)
f=input('Input frequency of the signal: f\n');
N=input('Input number of pointsl: N\n');
T=input('Input sampling time: T\n');
flag=input('Add zero too sampling signal or not? yes=1 no=0\n');
if(flag)
ZeroNum=input('Input nmber of zeros\n');
else
ZeroNum=0;
end
%生成信号,signal是原信号。signal为采样信号。
fs=1/T;
t=0:0.00001:T*(N+ZeroNum-1);
signal=sin(2*pi*f*t);
t2=0:T:T*(N+ZeroNum-1);
signal2=sin(2*pi*f*t2);
if (flag)
signal2=[signal2 zeros(1, ZeroNum)];
end
%画出原信号及采样信号。
figure;
subplot(2,1,1);
plot(t,signal);
xlabel('Time(s)');
ylabel('Amplitude(volt)');
title('Singnal');
hold on;
subplot(2,1,1);
stem(t2,signal2,'r');
axis([0 T*(N+ZeroNum) -1 1]);
%作FFT变换,计算其幅值,归一化处理,并画出频谱。
Y = fft(signal2,N);
Pyy = Y.* conj(Y) ;
Pyy=(Pyy/sum(Pyy))*2;
f=0:fs/(N-1):fs/2;4
subplot(2,1,2);
bar(f,Pyy(1:N/2));
xlabel('Frequency(Hz)');
ylabel('Amplitude');
title('Frequency compnents of signal');
axis([0 fs/2 0 ceil(max(Pyy))])
grid on;
祝你好运!
我可以帮助你,你先设置我最佳答案后,我百度Hii教你。
谁能给一个C语言的FFT算法程序啊,急用
typedef struct complex_struct
{
float real;
float img;
} complex;
void FFT(complex *TD,complex *FD,int r)
{
int count;
int i,j,k;
int bfsize,p;
float angle;
complex *W,*X1,*X2,*X;
W=w; X1=x1; X2=x2;
count=1<<r;
for ( i=0;i<count/2;i++ )
{
angle=-i*PI*2/count;
(W+i)->real=cos(angle);
(W+i)->img=sin(angle);
}
for ( i=0;i<count;i++ )
{
(X1+i)->real=(TD+i)->real;
(X1+i)->img=(TD+i)->img;
}
for ( k=0;k<r;k++ )
{
for ( j=0;j<1<<k;j++ )
{
bfsize=1<<(r-k);
for ( i=0;i<bfsize/2;i++ )
{
p=j*bfsize;
(X2+i+p)->real=(X1+i+p)->real+(X1+i+p+bfsize/2)->real;
(X2+i+p)->img=(X1+i+p)->img+(X1+i+p+bfsize/2)->img;
(X2+i+p+bfsize/2)->real=((X1+i+p)->real-(X1+i+p+bfsize/2)->real)
*(W+i*(1real-((X1+i+p)->img -(X1+i+p+bfsize/2)->img)*(W+i*(1img;
(X2+i+p+bfsize/2)->img=((X1+i+p)->real-(X1+i+p+bfsize/2)->real)
*(W+i*(1img+((X1+i+p)->img -(X1+i+p+bfsize/2)->img)*(W+i*(1real; }
}
X=X1; X1=X2; X2=X;
}
for ( j=0;j<count;j++ )
{
p = 0;
for ( i=0;i<r;i++ )
if ( j&(1<<i) )
p+=1<<(r-i-1);
(FD+j)->real=(X1+p)->real;
(FD+j)->img=(X1+p)->img;
}
}
怎样用C语言实现FFT算法啊?
1、二维FFT相当于对行和列分别进行一维FFT运算。具体的实现办法如下:先对各行逐一进行一维FFT,然后再对变换后的新矩阵的各列逐一进行一维FFT。相应的伪代码如下所示:for (int i=0; i<M; i++)FFT_1D(ROW[i],N);for (int j=0; j<N; j++)FFT_1D(COL[j],M);其中,ROW[i]表示矩阵的第i行。注意这只是一个简单的记法,并不能完全照抄。还需要通过一些语句来生成各行的数据。同理,COL[i]是对矩阵的第i列的一种简单表示方法。所以,关键是一维FFT算法的实现。2、例程:#include #include #include #define N 1000/*定义复数类型*/typedef struct{double real;double img;}complex;complex x[N], *W; /*输入序列,变换核*/int size_x=0; /*输入序列的大小,在本程序中仅限2的次幂*/double PI; /*圆周率*/void fft(); /*快速傅里叶变换*/void initW(); /*初始化变换核*/void change(); /*变址*/void add(complex ,complex ,complex *); /*复数加法*/void mul(complex ,complex ,complex *); /*复数乘法*/void sub(complex ,complex ,complex *); /*复数减法*/void output();int main(){int i; /*输出结果*/system("cls");PI=atan(1)*4;printf("Please input the size of x:\n");scanf("%d",&size_x);printf("Please input the data in x[N]:\n");for(i=0;i0 ){ j=j>1; } if(j>i){ temp=x[i]; x[i]=x[j]; x[j]=temp; }}}/*输出傅里叶变换的结果*/void output(){int i;printf("The result are as follows\n");for(i=0;i=0.0001)printf("+%.4fj\n",x[i].img); else if(fabs(x[i].img)real=a.real+b.real;c->img=a.img+b.img;}void mul(complex a,complex b,complex *c){c->real=a.real*b.real - a.img*b.img;c->img=a.real*b.img + a.img*b.real;}void sub(complex a,complex b,complex *c){c->real=a.real-b.real;c->img=a.img-b.img;}
求用matlab或者C语言实现的FFT变换程序
你好,这是我的回答,希望可以帮到你。
1)结果讨论
一,如果对信号进行同样点数N的FFT变换,采样频率fs越高,则可以分析越高频的信号;与此同时,采样频率越低,对于低频信号的频谱分辨率则越好。
二,假设采样点不在正弦信号的波峰、波谷、以及0电压处,频谱则会产生泄露(leakage)。
三,对于同样的采样率fs,提高FFT的点数N,则可提高频谱的分辨率。
四,如果采样频率fs小于2倍信号频率2*fs(奈圭斯特定理),则频谱分析结果会出错。
五,对于(二)中泄露现象,可以通过在信号后面补零点解决。
2)程序及注解如下
%清除命令窗口及变量
clc;
clear all;
%输入f、N、T、是否补零(补几个零)
f=input('Input frequency of the signal: f\n');
N=input('Input number of pointsl: N\n');
T=input('Input sampling time: T\n');
flag=input('Add zero too sampling signal or not? yes=1 no=0\n');
if(flag)
ZeroNum=input('Input nmber of zeros\n');
else
ZeroNum=0;
end
%生成信号,signal是原信号。signal为采样信号。
fs=1/T;
t=0:0.00001:T*(N+ZeroNum-1);
signal=sin(2*pi*f*t);
t2=0:T:T*(N+ZeroNum-1);
signal2=sin(2*pi*f*t2);
if (flag)
signal2=[signal2 zeros(1, ZeroNum)];
end
%画出原信号及采样信号。
figure;
subplot(2,1,1);
plot(t,signal);
xlabel('Time(s)');
ylabel('Amplitude(volt)');
title('Singnal');
hold on;
subplot(2,1,1);
stem(t2,signal2,'r');
axis([0 T*(N+ZeroNum) -1 1]);
%作FFT变换,计算其幅值,归一化处理,并画出频谱。
Y = fft(signal2,N);
Pyy = Y.* conj(Y) ;
Pyy=(Pyy/sum(Pyy))*2;
f=0:fs/(N-1):fs/2;4
subplot(2,1,2);
bar(f,Pyy(1:N/2));
xlabel('Frequency(Hz)');
ylabel('Amplitude');
title('Frequency compnents of signal');
axis([0 fs/2 0 ceil(max(Pyy))])
grid on;
祝你好运!
在Matlab中编程实现:N=2^L的按时间抽取和频率抽取的的FFT算法。
根据有限长序列离散傅里叶变换公式计算:f1=50; %10Hzf2=100; %100Hz%抽样频率Fs=1000; %100Hz%抽样点数NL=10;N=2^L;%抽样脉冲序列n = 0:N-1;t = n./Fs;% f2 一个周期的采样数M = floor(Fs/f2);%被采样信号x = cos(2*pi*f1.*t)+sin(2*pi*f2.*t);%采样序列subplot(311);stem(t(1:2*M),x(1:2*M));hold off;%傅里叶变换%根据有限长序列的离散傅里叶变换公式计算DFTn = 0:N-1;k = 0:N-1;F = x * exp(-j*2*pi/N).^(n'*k);subplot(312);plot(n,abs(F));subplot(313);plot(k,angle(F));
用matlab编写实现fft的程序。
function y=myditfft(x)
%本程序对输入序列实现DIT-FFT基2算法,点数取大于等于长度的2的幂次
%------------------------------------
% myditfft.c
%------------------------------------
m=nextpow2(x); %求的x长度对应的2的最低幂次m
N=2^m;
if length(x)<N
x=[x,zeros(1,N-length(x))]; %若的长度不是2的幂,补0到2的整数幂
end
nxd=bin2dec(fliplr(dec2bin([1:N]-1,m)))+1; %求1:2^m数列的倒序
y=x(nxd); %将倒序排列作为的初始值
for mm=1:m %将DFT做m次基2分解,从左到右,对每次分解作DFT运算
Nmr=2^mm;
u=1; %旋转因子u初始化
WN=exp(-i*2*pi/Nmr); %本次分解的基本DFT因子WN=exp(-i*2*pi/Nmr)
for j=1:Nmr/2 %本次跨越间隔内的各次碟形运算
for k=j:Nmr:N %本次碟形运算的跨越间隔为Nmr=2^mm
kp=k+Nmr/2; %确定碟形运算的对应单元下标
t=y(kp)*u; %碟形运算的乘积项
y(kp)=y(k)-t; %碟形运算的加法项
y(k)=y(k)+t;
end
u=u*WN; %修改旋转因子,多乘一个基本DFT因子WN
end
end
一维实序列的快速傅里叶变换(FFT)
通过前面的分析,我们认识到傅里叶变换本身是复数运算,地球物理获取的数据大多数是实数,对于实数的变换原则上可直接套用复序列的FFT算法,但那样是把实数序列当作虚部为零的复数对待,显然需要存储虚部的零并进行无功的运算,既浪费了一倍的计算内存,又降低了约一半的运算速度。为了不浪费不可不设的虚部内存和必然出现的复数运算,可否将一个实序列分为两个子实序列,分别作为实部与虚部构成一个复数序列,然后用复序列的FFT算法求其频谱,对合成的复序列频谱进行分离和加工得到原实序列的频谱呢?答案是肯定的,实现这一过程思路就是实序列FFT算法的基本思想。1.实序列的傅里叶变换性质对于一个N个样本的实序列x(k),其频谱为X(j),用Xr(j)和Xi(j)表示X(j)的实部和虚部, 表示X(j)的共轭,则 证明:已知 则地球物理数据处理基础上式两端取共轭,并注意到x(k)是实序列,则地球物理数据处理基础这就是实序列的傅里叶变换具有复共轭性。其同样具有周期性,即地球物理数据处理基础2.一维实序列的FFT算法(1)同时计算两个实序列的FFT算法已知两个实序列h(k),g(k)(k=0,1,…,N-1),例如重磁异常平面数据中的两条剖面,或地震勘探中的两道地震记录,可以人为地构成一个复序列:地球物理数据处理基础设h(k)的频谱为H(j)=Hr(j)+iHi(j)g(k)的频谱为G(j)=Gr(j)+iGi(j)y(k)的频谱为Y(j)=Yr(j)+i Yi(j)利用上节的复序列FFT算法,求得Y(j),即Yr(j)和Yi(j)已知,来寻找Hr(j),Hi(j),Gr(j),Gi(j)与Yr(j),Yi(j)之间的关系。对式(8-22)作傅里叶变换:地球物理数据处理基础由于H(j),G(j)本身是复序列,所以不能仅从上式分离出H(j)和G(j)。应用Y(j)的周期性,容易得到Y(N-j)=H(-j)+iG(-j)上式取共轭:地球物理数据处理基础由于h(k),g(k)为实序列,对上式右端应用复共轭定理,得地球物理数据处理基础对式(8-23)展开,得地球物理数据处理基础对式(8-24)展开,并应用共轭关系,得地球物理数据处理基础把式(8-25)和式(8-26)与Y(j)=Yr(j)+iYi(j)进行对比,有地球物理数据处理基础整理得地球物理数据处理基础因此,对于两个实序列,通过构造一个复序列,应用复序列的FFT算法和式(8-28)的分离加工,即可得到两个实序列的频谱。(2)计算2 N个数据点的实序列FFT算法设有2N点的实序列u(k)(k=0,1,…,2N-1),首先按k的偶、奇分成两个子实序列,并构成复序列,即地球物理数据处理基础通过调用复序列FFT算法,求得y(k)的频谱为Y(j)。另记h(k),g(k)的频谱为H(j)和G(j)。利用前面式(8-23)和式(8-24),容易求得地球物理数据处理基础下面分析用H(j),G(j)形成u(k)频谱的问题。记u(k)(k=0,1,…,2 N-1)的频谱为V(j),分析V(j),H(j),G(j)之间的关系,根据定义地球物理数据处理基础利用式(8-31)和式(8-34)可换算出u(k)的前N个频谱V(j)(j=0,1,…,N-1),还要设法求u(k)的后N个频谱V(N+j)(j=0,1,…,N-1)。利用实序列其频谱的复共轭和周期性:(1)H(N)=H(0),G(N)=G(0),WN1=-1,得地球物理数据处理基础(2)由于u(k)(k=0,1,…,2N-1)是实序列,同样利用实序列其频谱的复共轭和周期性,用已求出的前N个频谱V(j)表示出后面的N-1个频谱V(N+j):地球物理数据处理基础由于0<2N-j<N,所以可从V(j)(j=0,1,…,N-1)中选出V(2N-j)(j=N+1,N+2,…,2 N-1),并直接取其共轭 即可得到V(N+1)~V(2 N-1),从而完成整个实序列频谱的计算。总结以上叙述,一维实序列u(k)(k=0,1,…,2N-1)的FFT计算编程步骤如下:(1)按偶、奇拆分实序列u(k),并构造复序列:地球物理数据处理基础(2)调用复序列的FFT计算y(k)的频谱Y(j)(j=0,1,…,N-1);(3)用下式计算形成h(k),g(k)的频谱H(j)和G(j);地球物理数据处理基础(4)用下式换算实序列u(k)的频谱V(j)(j=0,1,…,2 N-1):地球物理数据处理基础[例3]求实序列样本u(k)={1,2,1,1,3,2,1,2}(k=0,1,…,7)的频谱。解:按偶、奇拆分实序列u(k),按式(8-37)构造复序列c(j)(j=0,1,2,3),即c(0)=1+2i; c(1)=1+i; c(2)=3+2i; c(3)=1+2i。(1)调用复序列FFT求c(j)(j=0,1,2,3)的频谱Z(k)(k=0,1,2,3),得Z(0)=6+7i; Z(1)=-3; Z(2)=2+i; Z(3)=-1。地球物理数据处理基础(3)运用公式(8-38)计算H(j),G(j):地球物理数据处理基础(4)根据式(8-39)求出u(k)(k=0,1,…,7)的8个频谱V(j)(j=0,1,…,7):地球物理数据处理基础地球物理数据处理基础由上例可见,完成全部2 N个实序列频谱的计算只需做N次FFT计算,相比直接用复序列的FFT算法节省了约一半的计算量。
傅里叶(FFT、DFT、傅立叶、Fourier)傅里叶变换的结果为什么含有复数?
第一,从定义式上看,积分号里含有复数,积分结果是复数;第二,从傅立叶变换的物理意义上看:FT变换是将一个信号分解为多个信号之和的形式,并且是正弦或余弦信号叠加的形式;我们知道,决定一个正弦波的是其振幅和相位,二者缺一不可。而实数只能表示振幅或者相位,而复数是二维平面上的,可以同时表示振幅和相位,所以用复数表示。频谱是复数形式,可以分解为振幅谱和相位谱,它们是实数形式。扩展资料:在一个以2T为周期内f(X)连续或只有有限个第一类间断点,附f(x)单调或可划分成有限个单调区间,则F(x)以2T为周期的傅里叶级数收敛,和函数S(x)也是以2T为周期的周期函数,且在这些间断点上,函数是有限值;在一个周期内具有有限个极值点;绝对可积。将满足一定条件的某个函数表示成三角函数(正弦和/或余弦函数)或者它们的积分的线性组合。在不同的研究领域,傅立叶变换具有多种不同的变体形式,如连续傅立叶变换和离散傅立叶变换。最初傅立叶分析是作为热过程的解析分析的工具被提出的。参考资料来源:百度百科--傅里叶变换
FFT的源码含义
在C环境下的源码源码(1):注:亲测,这个版本无法运行,作者删改了重要内容 请参考源码(2) //快速傅立叶变换// 入口参数:// l: l=0, 傅立叶变换;l=1, 逆傅立叶变换// il: il=0,不计算傅立叶变换或逆变换模和幅角;il=1,计算模和幅角// n: 输入的点数,为偶数,一般为32,64,128,...,1024等// k: 满足n=2^k(k>0),实质上k是n个采样数据可以分解为偶次幂和奇次幂的次数// pr[]: l=0时,存放N点采样数据的实部// l=1时, 存放傅立叶变换的N个实部// pi[]: l=0时,存放N点采样数据的虚部// l=1时, 存放傅立叶变换的N个虚部//// 出口参数:// fr[]: l=0, 返回傅立叶变换的实部// l=1, 返回逆傅立叶变换的实部// fi[]: l=0, 返回傅立叶变换的虚部// l=1, 返回逆傅立叶变换的虚部// pr[]: il=1,i=0 时,返回傅立叶变换的模// il=1,i=1 时,返回逆傅立叶变换的模// pi[]: il=1,i=0 时,返回傅立叶变换的辐角// il=1,i=1 时,返回逆傅立叶变换的辐角void fft(double pr[], double pi[], int n, int k, double fr[], double fi[], int l, int il){int it,m,is,i,j,nv,l0;double p,q,s,vr,vi,poddr,poddi;for(it=0;it=0;l0--){m/=2;nv0?90.0-90.0;elsepi=atan(fi/fr)*360.0/6.283185306;}return;}源码(2)ps:可以运行的 // The following line must be defined before including math.h to correctly define M_PI#define _USE_MATH_DEFINES#include #include #include #define PI M_PI /* pi to machine precision, defined in math.h */#define TWOPI (2.0*PI)/*FFT/IFFT routine. (see pages 507-508 of Numerical Recipes in C)Inputs:data[] : array of complex* data points of size 2*NFFT+1.data[0] is unused,* the n'th complex number x(n), for 0 = length(x).isign: if set to 1,computes the forward FFTif set to -1,computes Inverse FFT - in this case the output values haveto be manually normalized by multiplying with 1/NFFT.Outputs:data[] : The FFT or IFFT results are stored in data, overwriting the input.*/void four1(double data[], int nn, int isign){int n, mmax, m, j, istep, i;double wtemp, wr, wpr, wpi, wi, theta;double tempr, tempi;n = nn i) {tempr = data[j]; data[j] = data[i]; data[i] = tempr;tempr = data[j+1]; data[j+1] = data[i+1]; data[i+1] = tempr;}m = n >> 1;while (m >= 2 && j > m) {j -= m;m >>= 1;}j += m;}mmax = 2;while (n > mmax) {istep = 2*mmax;theta = TWOPI/(isign*mmax);wtemp = sin(0.5*theta);wpr = -2.0*wtemp*wtemp;wpi = sin(theta);wr = 1.0;wi = 0.0;for (m = 1; m * TD, complex * FD, int r){//一维快速Fourier变换。//complex * TD ——指向时域数组的指针; complex * FD ——指向频域数组的指针; r ——2的幂数,即迭代次数LONG count; // Fourier变换点数int i,j,k; // 循环变量int bfsize,p; // 中间变量double angle; // 角度complex *W,*X1,*X2,*X;count = 1 [count / 2];X1 = new complex[count];X2 = new complex[count]; // 分配运算所需存储器// 计算加权系数(旋转因子w的i次幂表)for(i = 0; i (cos(angle), sin(angle));}// 将时域点写入X1memcpy(X1, TD, sizeof(complex) * count);// 采用蝶形算法进行快速Fourier变换for(k = 0; k < r; k++){for(j = 0; j < 1 << k; j++){bfsize = 1 << (r-k);for(i = 0; i < bfsize / 2; i++){p = j * bfsize;X2[i + p] = X1[i + p] + X1[i + p + bfsize / 2] * W[i * (1<<k)];X2[i + p + bfsize / 2] = X1[i + p] - X1[i + p + bfsize / 2] * W[i * (1<<k)];}}X = X1;X1 = X2;X2 = X;}// 重新排序for(j = 0; j < count; j++){p = 0;for(i = 0; i < r; i++){if (j&(1<<i)){p+=1<<(r-i-1);}}FD[j]=X1[p];}// 释放内存delete W;delete X1;delete X2;return true;}在Matlab环境下的源码function X=myfft(x)N=length(x);if N==1X=x;return;end%myfft函数 用递归实现t=log2(N);t1=floor(t);t2=ceil(t);if t1~=t2; %若x的长度N不为2的整数次幂,则补0至最接近的2的整数次幂x=[x zeros(1,2^t2-N)];N=2^t2;endw0=exp(-1i*2*pi/N);X=zeros(1,N);n=1:N/2;xo(n)=x(2*n-1);xe(n)=x(2*n);XO=myfft(xo); %递归调用XE=myfft(xe);for n=1:N/2X(n)=XO(n)+XE(n)*(w0^(n-1));X(n+N/2)=XO(n)-XE(n)*(w0^(n-1));end
求matlab的fft源程序
快速卷积实验:傅立叶变换一个重要特性是可以实现快速卷积。
设A为M×N矩阵,B为P×Q的矩阵,快速卷积方法如下:
*对A和B补0,使其大小都为(M+P-1)×(N+Q-1)
*利用fft2对矩阵A和B进行二维变换
*将两个FFT结果相乘,利用ifft2对得到的乘积进行傅立叶反变换
现在令A=magic(3),B=ones(3),请按上述步骤自行完成实验。
―――――――――――――――――――――――――――――――――――――――
参考如下:
启动MATLAB,在命令窗口中输入
A=magic(3);
B=ones(3);
A(8,8)=0;
B(8,8)=0;
C=ifft2(fft2(A).*fft2(B));
C=C(1:5,1:5);
C=real(C)
―――――――――――――――――――――――――――――――――――――――
(1)观察运行结果,并记录。
(2)调用MATLAB提供的卷积函数conv2进行验证,对比结果是否正确
C=conv2(A,B);
C=C(1:5,1:5)
运行并对比记录结果。