C++实现离散傅里叶变换的快速算法(FFT)

C++实现离散傅⾥叶变换的快速算法(FFT)前⾔:近期作为⼩⽩在学习FFT,故写此⽂,⼀来提⾼对FFT的领悟程度,⽽来求⼤神指导。
三、 FFT的C++代码设计的
1、 步骤
(1) 将原序列变化为序号为逆序的序列;
(2) 设总点数N为2的m次⽅,那么经过m级分解后就可以进⾏2点DFT运算
(3) 从左到右规律,对第i级分解(i=0、1、2…m),有规律:①要进⾏2i次运算③2组蝶形运算之间的序号间隔为2^(i+1) ,④每组蝶形运算内部2个数之间的序号间隔为2^i。
(4) 由于蝶形运算是复数计算。因此可以选择将最终结果表达为模和辐⾓的形式,也可以表达为实部和虚部的形式,通常选择前者。本⽂采取的是输出2个数组,1数组个存储幅值(模),1个数组存储辐⾓。取出即将进⾏蝶形计算的2个数,分解成实部和虚部的形式,计算旋转因⼦。根据蝶形运算规则完成计算,再将实部和虚部形式转换成模和辐⾓的形式
/*
1、amp :幅值存储空间;phase :相位存储空间,
2、m :存储长度为2^m 次(m >=1 ),在函数外保证
*/
void  FFT (double  *amp , double  *phase , int  m )
{
double  pi = 3.14159265358979323846 ;  //定义π的值
//将数据序列按逆序排列
double  temp ;
int  i_temp ; //中间临时数据
int  nixu ;  //数据的逆序下标
// 1<<m 即 2^m
烯丙基苯for  (int  i = 0 ; i < (1<<m ) ; i ++)
{
i_temp = i ; // i 是顺序下标
nixu = 0 ; // 逆序下标
for  (int  j = 0; j < m ; j ++)
{
nixu = nixu << 1 ;    // 逆序下标向左移⼀位,腾出最低位,准备接收数据
nixu = nixu | (i_temp & 0x01) ; // 将顺序下标的的最低位取出放到逆序下标的最低位上
i_temp = i_temp >> 1 ;    // 顺序下标向右移⼀位,准备下次取最低位葛守江
}
//按顺序下标的顺序依次计算逆序下标后,将顺序、逆序位置的数据交换。培智学校
//出现顺序下标的值⼤于逆序下标时就不交换,因为在顺序下标⼩的时候已经交换过了。
if  ( nixu > i )
{
temp = *(amp + i ) ;
*(amp + i ) = *(amp + nixu );
*(amp + nixu ) = temp ;
(m-1-i)组蝶形运算②每组蝶形运算依次进⾏2
*(amp + nixu)= temp ;
}
*(phase + i )=0;// 相位数据置0
}
// 最外层循环,按分解的级数进⾏循环
double real_X1 , real_X2 ,real_T1 ,real_T2 ;
double imag_X1 , imag_X2 ,imag_T1 ,imag_T2;
double rad_WnK =0;
int  D1 , D2 , index1 , index2;
// 分解为m级
for(int i =0; i < m; i++)
{
D1 =1<< i ;// 2^i  //  蝶形计算内部2个数的序号间隔
D2 =2<< i ;// 2^(i+1) // 两组蝶形计算间的序号间隔
// j < nLength/2^(i-1) ;
for(int j =0; j <(1<<(m-1-i)); j++)
{
for(int k =0; k  <(1<< i); k ++)
{
rad_WnK =0- k * pi /(1<< i );//旋转因⼦的⾓度
index1 = D2 * j + k  ;// 蝶形运算第⼀个数的下标
index2 = D2 * j + k + D1 ;// 蝶形运算第⼆个数的下标
//蝶形运算第⼀个数的实部和虚部
real_X1 =*(amp + index1 )*cos(*(phase + index1));
imag_X1 =*(amp + index1 )*sin(*(phase + index1));
//临时存储蝶形运算第⼀个数的实部和虚部
怀柔一中real_T1 = real_X1 ;
imag_T1 = imag_X1 ;
//蝶形运算第⼆个数的实部和虚部
real_X2 =*(amp + index2 )*cos(*(phase + index2));
imag_X2 =*(amp + index2 )*sin(*(phase + index2));
//蝶形运算第⼀个数乘以旋转因⼦后的实部和虚部
real_T2 =*(amp + index2 )*cos(*(phase + index2)+ rad_WnK );    imag_T2 =*(amp + index2 )*sin(*(phase + index2)+ rad_WnK );
//蝶形运算主体
核酸提取
real_X1 = real_X1 + real_T2 ;
imag_X1 = imag_X1 + imag_T2 ;
real_X2 = real_T1 - real_T2 ;
imag_X2 = imag_T1 - imag_T2 ;
// 将实部、虚部转换成模和⾓
*(amp + index1 )=sqrt(real_X1 * real_X1 + imag_X1 * imag_X1);
//处理模为0的情况
if(*(amp + index1 )<1E-100)
{
中国农民调查 pdf
*(amp + index1 )=1E-100;
}
*(phase + index1 )=acos( real_X1 /*(amp + index1 ));
if(imag_X1 <0)
{
*(phase + index1 )=0-*(phase + index1 );
}
*(amp + index2 )=sqrt(real_X2 * real_X2 + imag_X2 * imag_X2);
//处理模为0的情况
if(*(amp + index2 )<1E-100)
{
*(amp + index2 )=1E-100;
}
*(phase + index2 )=acos( real_X2 /*(amp + index2 ));
if(imag_X2 <0)
{
*(phase + index2 )=0-*(phase + index2 );
}
}
}
}
}

本文发布于:2024-09-21 12:38:31,感谢您对本站的认可!

本文链接:https://www.17tex.com/xueshu/486229.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:蝶形   个数   运算   逆序   顺序   计算   下标
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议