快速傅里叶变换FFT的代码实现

本文将根据离散傅里叶变换的快速算法编写代码

1,首先列出DFT的变换式和快速计算公式

X(k)=\sum_{n=0}^{N-1}x(n)W_N^{nk}

X(k)=X_1(k)+X_2(k)W_N^k

X(k)=X_1(k)-X_2(k)W_N^k

2,假定N=2^L,那么采用基拆分具有如下树状规律

3,下面在表格里面列出快速算法的一般规律:

 左子树右子树序列分组组内分对W(N,k)
第1层b[L-1]=0b[L-1]=12^(L-1)2^(1-1)N=2^1,k=[0~2^(1-1)-1]
第2层b[L-2]=0b[L-2]=12^(L-2)2^(2-1)N=2^2,k=[0~2^(2-1)-1]
..................
第i层b[L-i]=0b[L-i]=12^(L-i)2^(i-1)N=2^i,k=[0~2^(i-1)-1]
............... 
第L层b[L-L]=0b[L-L]=12^(L-L)2^(L-1)N=2^L,k=[0~2^(L-1)-1]
      

 

 

 

 

 

 

 

 

 

 

4,运算的时候,从序号的高位进行,向低位滑行。需要注意的是取k值,即是蓝色区域的数值需要按位逆序运算。完整的代码如下:

function X_k=fft2_dit(x_n)
    N1 =length(x_n);
    L  =ceil(log2(N1));
    N  =2^L;
    X_t=zeros(1,N);
    %如果序列不是2整数次幂,那么进行补零处理
    for m=1:N
        if(m<=N1)
            X_t(m)=x_n(m);
        else
            X_t(m)=0;
        end
    end
    for m=1:L %层级循环
        N     =2^m;%W(N,k)中N值
        k_max =N/2 -1;%W(N,k)中最大k值
        g_max =2^(L-m);%一层有多少组独立的蝶形图
       for g=1:g_max %层内分组    
            for p=0:k_max %组内分对                
                k=0; %k值逆序运算
                for n=1:m-1
                    k=bitshift(k,1) + bitget(p,n);      
                end    
                num_1     =(2*p+0)*g_max+ g;
                num_2     =(2*p+1)*g_max+ g; 
                X1        =X_t(num_1) + X_t(num_2)*exp(-1j*2*pi*k/N);
                X2        =X_t(num_1) - X_t(num_2)*exp(-1j*2*pi*k/N);
                X_t(num_1)=X1;
                X_t(num_2)=X2;                 
            end
       end
    end
   
    X_k=zeros(1,N);    
    for m=0:2^L-1
        k=0; %输出逆序运算    
        for n=1:L
            k=bitshift(k,1) + bitget(m,n);      
        end
        X_k(m+1)=X_t(k+1);
    end
end

5,下面测试按时间基2拆分的正确性

x_n =[0 1 2 3 4 5 6 7];
Xk  =fft2_dit(x_n);%测试输出
Xp  =fft(x_n);%使用matlab自带的函数
Xk =Xk.'
Xp =Xp.'

测试结果如下
Xk =

  28.0000          
  -4.0000 + 9.6569i
  -4.0000 + 4.0000i
  -4.0000 + 1.6569i
  -4.0000          
  -4.0000 - 1.6569i
  -4.0000 - 4.0000i
  -4.0000 - 9.6569i


Xp =

  28.0000          
  -4.0000 + 9.6569i
  -4.0000 + 4.0000i
  -4.0000 + 1.6569i
  -4.0000          
  -4.0000 - 1.6569i
  -4.0000 - 4.0000i
  -4.0000 - 9.6569i


6,首先列出DFT的变换式和快速计算公式

X(k)=\sum_{n=0}^{N-1}x(n)W_N^{nk}

x_1(n)=x(n)+x(n+\frac{N}{2})

x_1(n)=[x(n)-x(n+\frac{N}{2})]W_N^n

7,分析之后可以发现,每进行一层蝶形计算之后,序列对折一半。显然对折的比特位从最高位开始,直到最低位结束,层层依次迭代。因为每进行一层运算,频域值得序号进行一次奇偶交换,等于频域值对折的比特位从最低位开始,直到最高位结束。需要注意的是k值不会有逆序的操作。最后得到的频域值,进行一次逆序操作。程序如下:

function X_k=fft2_dif(x_n)
    N1 =length(x_n);
    L  =ceil(log2(N1));
    N  =2^L;
    X_t=zeros(1,N);
    %如果序列不是2整数次幂,那么进行补零处理
    for m=1:N
        if(m<=N1)
            X_t(m)=x_n(m);
        else
            X_t(m)=0;
        end
    end
    for m=1:L %层级循环
        N     =2^(L-m+1);%W(N,k)中N值
        k_max =N/2-1;%W(N,k)中最大k值
        g_max =2^(m-1);%一层有多少组独立的蝶形图
       for g=0:g_max-1 %层内分组    
            for k=0:k_max %组内分对                 
                num_1     =(2*g+0)*2^(L-m)+ k+1;
                num_2     =(2*g+1)*2^(L-m)+ k+1; 
                X1        =X_t(num_1) + X_t(num_2);
                X2        =(X_t(num_1) - X_t(num_2))*exp(-1j*2*pi*k/N);
                X_t(num_1)=X1;
                X_t(num_2)=X2;                 
            end
       end
    end
   
    X_k=zeros(1,N);    
    for m=0:2^L-1
        k=0; %输出逆序运算    
        for n=1:L
            k=bitshift(k,1) + bitget(m,n);      
        end
        X_k(m+1)=X_t(k+1);
    end
end

8,下面测试按频率基2拆分的正确性

x_n =[0 1 2 3 4 5 6 7 8 7 6 5 4 3 2 1];
Xk  =fft2_dit(x_n);%测试输出
Xp  =fft(x_n);%使用matlab自带的函数
Xk  =Xk.'
Xp  =Xp.'

测试结果如下

Xk =

  64.0000          
 -26.2741 - 0.0000i
        0          
  -3.2398 - 0.0000i
        0          
  -1.4465 + 0.0000i
        0          
  -1.0396 + 0.0000i
        0          
  -1.0396 + 0.0000i
        0          
  -1.4465 + 0.0000i
        0          
  -3.2398 + 0.0000i
        0          
 -26.2741 - 0.0000i


Xp =

   64.0000
  -26.2741
         0
   -3.2398
         0
   -1.4465
         0
   -1.0396
         0
   -1.0396
         0
   -1.4465
         0
   -3.2398
         0
  -26.2741


自此,快速傅里叶算法研究到此结束,如果对你有所帮助,请点一个赞,谢谢。

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值