打印
[学习资料]

使用C语言实现FFT算法

[复制链接]
816|17
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
juliestephen|  楼主 | 2023-4-23 13:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#define N 1024
#define PI 3.1415

/*复数结构体类型*/
typedef struct{
double realPart;
double imaginaryPart;
}complexNumber;

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


int main()
{
        printf("请输入序列的长度:");              //输入序列的大小
        scanf("%d",&size_x);
        printf("\n请分别输入序列的实部和虚部\n");  //输入序列的实部和虚部
        for(int i=0;i<size_x;i++)
        {
                printf("请输入第%d个序列的实部:",i);
                scanf("%lf",&x[i].realPart);
                printf("请输入第%d个序列的虚部:",i);
                scanf("%lf",&x[i].imaginaryPart);
        }
        printf("\n输出原序列:\n");
        outputArray();
        initRotationFactor();  //生成旋转因子数组
        fastFourierOperation();//调用快速傅里叶变换
        printf("\n输出FFT后的结果:\n");
        outputArray();         //遍历输出数组
        return 0;
}


/*快速傅里叶变换*/
void fastFourierOperation()
{
        int l=0;
        complexNumber up,down,product;
        changePosition();                  //偶奇变换算法
        for(int i=0;i<size_x/2;i++)        //一级蝶形运算
        {   
                l=1<<i;
                for(int j=0;j<size_x;j+= 2*l ) //一组蝶形运算
                {            
                        for(int k=0;k<l;k++)       //一个蝶形运算
                        {      
                                mul(x[j+k+l],W[size_x*k/2/l],&product);
                                add(x[j+k],product,&up);
                                sub(x[j+k],product,&down);
                                x[j+k]=up;
                                x[j+k+l]=down;
                        }
                }
        }
}


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


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

        for (int i=0;i<size_x-1;i++)
        {
                if(i<j)
                {
                        //若倒序数大于顺序数,进行变址(换位);否则不变,防止重复交换,变回原数
                        temp=x[i];
                        x[i]=x[j];
                        x[j]=temp;
                }
                k=size_x/2;    //判断j的最高位是否为0
                while(j>=k)
                {              //最高位为1
                        j=j-k;
                        k=k/2;
                }
                j=j+k;        //最高位为0
        }
          printf("\n输出倒序后的结果:\n");
        outputArray();
}


/*遍历输出数组*/
void outputArray()
{
        for(int i=0;i<size_x;i++)
        {
                if(x[i].imaginaryPart<0){
                        printf("%.4f-j%.4f\n",x[i].realPart,abs(x[i].imaginaryPart));
                }
                else{
                        printf("%.4f+j%.4f\n",x[i].realPart,x[i].imaginaryPart);
                }
        }
}

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

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

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


使用特权

评论回复
沙发
zhuotuzi| | 2023-4-23 14:11 | 只看该作者
学习了,这个一直没学会。

使用特权

评论回复
板凳
mikewen| | 2023-5-7 08:25 | 只看该作者
How fast?

使用特权

评论回复
地板
tifmill| | 2023-5-7 16:57 | 只看该作者
傅里叶变换用C语言程序怎么实现?

使用特权

评论回复
5
vivilyly| | 2023-5-7 17:49 | 只看该作者
FFT算法可分为按时间抽取算法和按频率抽取算法

使用特权

评论回复
6
minzisc| | 2023-5-7 18:03 | 只看该作者
在实际应用中,需要对FFT算法进行优化以提高性能,并注意处理可能出现的边界和精度问题。

使用特权

评论回复
7
sdCAD| | 2023-5-7 18:12 | 只看该作者
FFT的公式是什么和算法是怎样实现

使用特权

评论回复
8
belindagraham| | 2023-5-7 19:52 | 只看该作者
对原始数据进行预处理,例如将时域采样点排列成复数序列。
利用蝴蝶操作(Butterfly Operation)将时域序列分解为多个子序列。
分别对每个子序列进行递归调用FFT算法,并将结果合并。
最终得到一个包含频域信息的复数序列。

使用特权

评论回复
9
yeates333| | 2023-5-7 20:12 | 只看该作者
FFT运算,在信号处理中是怎样运用的

使用特权

评论回复
10
usysm| | 2023-5-7 21:07 | 只看该作者
求matlab 快速傅立叶变换fft的算法详解?

使用特权

评论回复
11
1988020566| | 2023-5-7 21:37 | 只看该作者
FFT算法是一种高效的信号处理算法,可用于从时间域转换到频率域。

使用特权

评论回复
12
麻花油条| | 2023-5-8 16:47 | 只看该作者
论坛有歪果仁吗

使用特权

评论回复
13
tpgf| | 2023-5-10 17:02 | 只看该作者
FFT是一种DFT的高效算法,称为快速傅立叶变换

使用特权

评论回复
14
qcliu| | 2023-5-10 17:26 | 只看该作者
傅里叶变换是时域一频域变换分析中最基本的方法之一

使用特权

评论回复
15
caigang13| | 2023-5-10 18:11 | 只看该作者
单片机使用FFT算法,最好是内部带FPU单元。

使用特权

评论回复
16
drer| | 2023-5-11 08:14 | 只看该作者
FFT算法可分为按时间抽取算法和按频率抽取算法

使用特权

评论回复
17
coshi| | 2023-5-11 08:33 | 只看该作者
最常用的时域抽选方法是按奇偶将长序列不断地变为短序列,结果使输入序列为倒序,输出序列为顺序排列,这就是Coolly—Tukey算法

使用特权

评论回复
18
kxsi| | 2023-5-11 11:11 | 只看该作者
我们可以用FFT计算线性卷积。线性卷积是求离散系统响应的主要方法之一,许多重要应用都建立在这一理论基础上,如卷积滤波等。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

32

主题

1261

帖子

2

粉丝