[学习资料] 使用C语言实现FFT算法

[复制链接]
1378|17
 楼主| juliestephen 发表于 2023-4-23 13:00 | 显示全部楼层 |阅读模式
  1. #include <stdio.h>
  2. #include <math.h>
  3. #include <stdlib.h>
  4. #define N 1024
  5. #define PI 3.1415

  6. /*复数结构体类型*/
  7. typedef struct{
  8. double realPart;
  9. double imaginaryPart;
  10. }complexNumber;

  11. complexNumber x[N], W[N/2]; //序列数组以及旋转因子数组
  12. int size_x=0;               //输入序列的长度,只能为2的次幂
  13. void fastFourierOperation();//快速傅里叶变换算法
  14. void initRotationFactor();  //生成旋转因子数组
  15. void changePosition();      //偶奇变换算法
  16. void outputArray();         //遍历输出数组
  17. void add(complexNumber ,complexNumber ,complexNumber*); //复数加法
  18. void mul(complexNumber ,complexNumber ,complexNumber*); //复数乘法
  19. void sub(complexNumber ,complexNumber ,complexNumber*); //复数减法


  20. int main()
  21. {
  22.         printf("请输入序列的长度:");              //输入序列的大小
  23.         scanf("%d",&size_x);
  24.         printf("\n请分别输入序列的实部和虚部\n");  //输入序列的实部和虚部
  25.         for(int i=0;i<size_x;i++)
  26.         {
  27.                 printf("请输入第%d个序列的实部:",i);
  28.                 scanf("%lf",&x[i].realPart);
  29.                 printf("请输入第%d个序列的虚部:",i);
  30.                 scanf("%lf",&x[i].imaginaryPart);
  31.         }
  32.         printf("\n输出原序列:\n");
  33.         outputArray();
  34.         initRotationFactor();  //生成旋转因子数组
  35.         fastFourierOperation();//调用快速傅里叶变换
  36.         printf("\n输出FFT后的结果:\n");
  37.         outputArray();         //遍历输出数组
  38.         return 0;
  39. }


  40. /*快速傅里叶变换*/
  41. void fastFourierOperation()
  42. {
  43.         int l=0;
  44.         complexNumber up,down,product;
  45.         changePosition();                  //偶奇变换算法
  46.         for(int i=0;i<size_x/2;i++)        //一级蝶形运算
  47.         {   
  48.                 l=1<<i;
  49.                 for(int j=0;j<size_x;j+= 2*l ) //一组蝶形运算
  50.                 {            
  51.                         for(int k=0;k<l;k++)       //一个蝶形运算
  52.                         {      
  53.                                 mul(x[j+k+l],W[size_x*k/2/l],&product);
  54.                                 add(x[j+k],product,&up);
  55.                                 sub(x[j+k],product,&down);
  56.                                 x[j+k]=up;
  57.                                 x[j+k+l]=down;
  58.                         }
  59.                 }
  60.         }
  61. }


  62. /*生成旋转因子数组*/
  63. void initRotationFactor()
  64. {
  65.         for(int i=0;i<size_x/2;i++)
  66.         {
  67.                 W[i].realPart=cos(2*PI/size_x*i);//用欧拉公式计算旋转因子
  68.                 W[i].imaginaryPart=-1*sin(2*PI/size_x*i);
  69.         }
  70. }


  71. /*偶奇变换算法*/
  72. void changePosition()      
  73. {
  74.         int j=0,k;//待会儿进行运算时需要用到的变量
  75.         complexNumber temp;

  76.         for (int i=0;i<size_x-1;i++)
  77.         {
  78.                 if(i<j)
  79.                 {
  80.                         //若倒序数大于顺序数,进行变址(换位);否则不变,防止重复交换,变回原数
  81.                         temp=x[i];
  82.                         x[i]=x[j];
  83.                         x[j]=temp;
  84.                 }
  85.                 k=size_x/2;    //判断j的最高位是否为0
  86.                 while(j>=k)
  87.                 {              //最高位为1
  88.                         j=j-k;
  89.                         k=k/2;
  90.                 }
  91.                 j=j+k;        //最高位为0
  92.         }
  93.           printf("\n输出倒序后的结果:\n");
  94.         outputArray();
  95. }


  96. /*遍历输出数组*/
  97. void outputArray()
  98. {
  99.         for(int i=0;i<size_x;i++)
  100.         {
  101.                 if(x[i].imaginaryPart<0){
  102.                         printf("%.4f-j%.4f\n",x[i].realPart,abs(x[i].imaginaryPart));
  103.                 }
  104.                 else{
  105.                         printf("%.4f+j%.4f\n",x[i].realPart,x[i].imaginaryPart);
  106.                 }
  107.         }
  108. }

  109. /*复数加法的定义*/
  110. void add(complexNumber a,complexNumber b,complexNumber *c)
  111. {
  112.         c->realPart=a.realPart+b.realPart;
  113.         c->imaginaryPart=a.imaginaryPart+b.imaginaryPart;
  114. }

  115. /*复数乘法的定义*/
  116. void mul(complexNumber a,complexNumber b,complexNumber *c)
  117. {
  118.         c->realPart=a.realPart*b.realPart - a.imaginaryPart*b.imaginaryPart;
  119.         c->imaginaryPart=a.realPart*b.imaginaryPart + a.imaginaryPart*b.realPart;
  120. }

  121. /*复数减法的定义*/
  122. void sub(complexNumber a,complexNumber b,complexNumber *c)
  123. {
  124.         c->realPart=a.realPart-b.realPart;
  125.         c->imaginaryPart=a.imaginaryPart-b.imaginaryPart;
  126. }


zhuotuzi 发表于 2023-4-23 14:11 | 显示全部楼层
学习了,这个一直没学会。
mikewen 发表于 2023-5-7 08:25 | 显示全部楼层
How fast?
tifmill 发表于 2023-5-7 16:57 | 显示全部楼层
傅里叶变换用C语言程序怎么实现?
vivilyly 发表于 2023-5-7 17:49 | 显示全部楼层
FFT算法可分为按时间抽取算法和按频率抽取算法
minzisc 发表于 2023-5-7 18:03 | 显示全部楼层
在实际应用中,需要对FFT算法进行优化以提高性能,并注意处理可能出现的边界和精度问题。
sdCAD 发表于 2023-5-7 18:12 | 显示全部楼层
FFT的公式是什么和算法是怎样实现
belindagraham 发表于 2023-5-7 19:52 | 显示全部楼层
对原始数据进行预处理,例如将时域采样点排列成复数序列。
利用蝴蝶操作(Butterfly Operation)将时域序列分解为多个子序列。
分别对每个子序列进行递归调用FFT算法,并将结果合并。
最终得到一个包含频域信息的复数序列。
yeates333 发表于 2023-5-7 20:12 | 显示全部楼层
FFT运算,在信号处理中是怎样运用的
usysm 发表于 2023-5-7 21:07 | 显示全部楼层
求matlab 快速傅立叶变换fft的算法详解?
1988020566 发表于 2023-5-7 21:37 | 显示全部楼层
FFT算法是一种高效的信号处理算法,可用于从时间域转换到频率域。
麻花油条 发表于 2023-5-8 16:47 来自手机 | 显示全部楼层
论坛有歪果仁吗
tpgf 发表于 2023-5-10 17:02 | 显示全部楼层
FFT是一种DFT的高效算法,称为快速傅立叶变换
qcliu 发表于 2023-5-10 17:26 | 显示全部楼层
傅里叶变换是时域一频域变换分析中最基本的方法之一
caigang13 发表于 2023-5-10 18:11 来自手机 | 显示全部楼层
单片机使用FFT算法,最好是内部带FPU单元。
drer 发表于 2023-5-11 08:14 | 显示全部楼层
FFT算法可分为按时间抽取算法和按频率抽取算法
coshi 发表于 2023-5-11 08:33 | 显示全部楼层
最常用的时域抽选方法是按奇偶将长序列不断地变为短序列,结果使输入序列为倒序,输出序列为顺序排列,这就是Coolly—Tukey算法
kxsi 发表于 2023-5-11 11:11 | 显示全部楼层
我们可以用FFT计算线性卷积。线性卷积是求离散系统响应的主要方法之一,许多重要应用都建立在这一理论基础上,如卷积滤波等。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

32

主题

1529

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部