zoukankan      html  css  js  c++  java
  • 快速傅里叶变换(正/反)

    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    #define PI 3.141592653589793238462643383279 //这三十位的PI我小学就会背了

    void fft_rec(int N,int offset,int delta,double (*x)[2],double (*X)[2],double (*XX)[2])
    {
    int N2=N/2;
    int k;
    double cs,sn;
    int k00,k01,k10,k11;
    double tmp0,tmp1;

    if(N != 2)
    {
    fft_rec(N2, offset, 2*delta, x, XX, X);
    fft_rec(N2, offset+delta, 2*delta, x, XX, X);

    for(k=0; k<N2; k++)
    {
    k00 = offset + k*delta; k01 = k00 + N2*delta;
    k10 = offset + 2*k*delta; k11 = k10 + delta;
    cs = cos(2*PI*k/(double)N); sn = sin(2*PI*k/(double)N);
    tmp0 = cs * XX[k11][0] + sn * XX[k11][1];
    tmp1 = cs * XX[k11][1] - sn * XX[k11][0];
    X[k01][0] = XX[k10][0] - tmp0;
    X[k01][1] = XX[k10][1] - tmp1;
    X[k00][0] = XX[k10][0] + tmp0;
    X[k00][1] = XX[k10][1] + tmp1;
    }
    }
    else
    {
    k00 = offset; k01 = k00 + delta;
    X[k01][0] = x[k00][0] - x[k01][0];
    X[k01][1] = x[k00][1] - x[k01][1];
    X[k00][0] = x[k00][0] + x[k01][0];
    X[k00][1] = x[k00][1] + x[k01][1];
    }
    }

    void fft(int N,double (*x)[2],double (*X)[2])
    {
    double (*XX)[2]=malloc(2*N*sizeof(double));
    fft_rec(N,0,1,x,X,XX);
    free(XX);
    }

    void ifft(int N, double (*x)[2], double (*X)[2])
    {
    int N2 = N/2;
    int i;
    double tmp0, tmp1;

    fft(N, X, x);
    x[0][0] = x[0][0]/N;
    x[0][1] = x[0][1]/N;
    x[N2][0] = x[N2][0]/N;
    x[N2][1] = x[N2][1]/N;
    for(i=1; i<N2; i++)
    {
    tmp0 = x[i][0]/N;
    tmp1 = x[i][1]/N;

    x[i][0] = x[N-i][0]/N;
    x[i][1] = x[N-i][1]/N;

    x[N-i][0] = tmp0;
    x[N-i][1] = tmp1;
    }
    }

    int main()
    {
    int N; //N点FFT变换,数据的个数
    int i; //通用索引变量
    double dummy; //随便起的名字
    double (*x)[2]; //时域采样,x[i][0]实部,x[i][1]虚部
    double (*X)[2]; //频域采样,X[i][0]实部,X[i][1]虚部
    FILE *fp; //文件指针
    char *file="C:\\Users\\tc\\Documents\\Visual Studio 2010\\Projects\\fftc\\Debug\\data.txt"; //data.txt文件全路径
    N=0;

    if (!(fp=fopen(file,"r")))
    {
    printf("file not read data");
    system("pause");
    return 0;
    }

    while (fscanf(fp, "%lg%lg",&dummy,&dummy)==2)
    N++;
    printf("N=%d",N);

    if (N>=2)
    {
    i=N;
    while(i==2*(i/2))
    i=i/2;
    }

    if (N<2 || i!=1)
    {
    printf(",must equal 2^n for an integer n>=1");
    system("pause");
    return 0;
    }

    x=malloc(2*N*sizeof(double));
    X=malloc(2*N*sizeof(double));

    rewind(fp); //重置文件指针

    for (i=0;i<N;i++)
    fscanf(fp,"%lg%lg",&x[i][0],&x[i][1]); //读取文件数据,赋为时域采样值
    fclose(fp); //关闭文件

    printf("\n时域采样数据x(n):\n"); //显示原始数据
    for (i=0;i<N;i++)
    {
    printf("%12f %12f\n",x[i][0],x[i][1]);
    }

    fft(N,x,X); //正变换函数

    printf("\n频域变换数据X(k):\n"); //显示正变换后的数据
    for (i=0;i<N;i++)
    {
    printf("%12f %12f\n",X[i][0],X[i][1]);
    x[i][0]=0;
    x[i][1]=0;
    }

    ifft(N,x,X); //反变换函数

    printf("\n再反变换后时域数据x(n):\n"); //显示反变换后的数据,理论上和原数据一致
    for (i=0;i<N;i++)
    {
    printf("%12f %12f\n",x[i][0],x[i][1]);
    }
    free(x);
    free(X);

    system("pause");
    return 0;
    }

    data.txt:

    3.6 2.6
    2.9 6.3
    5.6 4.0
    4.8 9.1
    3.3 0.4
    5.9 4.8
    5.0 2.6
    4.3 4.1

    受朋友所托,写了这样的一个程序,参考了加州理工一个老外的程序。

  • 相关阅读:
    排序sort (一)
    c++实现二叉树笔记(模板实现)(三)
    树(二叉树)的建立和遍历算法(二)
    IO流之字节流
    计算机基础知识
    计算机启动过程
    2020软考报名计划表
    2020软件工程作业02
    初来乍到 20200904
    关于考研
  • 原文地址:https://www.cnblogs.com/tiandsp/p/2398771.html
Copyright © 2011-2022 走看看