zoukankan      html  css  js  c++  java
  • [C++]自编FFT(递归形式)

    1、对C++的运算符重载不太熟悉,所以相关复数运算操作是通过定义静态函数来操作;

    2、C++的类变量貌似和java定义类变量机制不一样,PI只能用宏来定义了。

    复数类:

     1 #pragma once#
     2 #include <math.h>
     3 class CComplex/*复数运算类*/
     4 {
     5 private:
     6     double m_real;   /*实部*/
     7     double m_img ;   /*虚部*/
     8 
     9 public:
    10     /*构造函数和析构函数*/
    11     CComplex();
    12     CComplex(CComplex &c);
    13     CComplex(double real, double img);
    14     ~CComplex();
    15     /* setters & getters */
    16     void    setReal ( double value   );
    17     double   getReal (   );
    18     void    setImg  ( double value   );
    19     double   getImg  ( );
    20 
    21     /*加法*/
    22     static void add(CComplex &c1 ,CComplex &c2 ,CComplex &c3)
    23     {
    24         double _real = c1.getReal() + c2.getReal();
    25         double _img = c1.getImg() + c2.getImg();
    26         c3.setReal(_real);
    27         c3.setImg(_img);
    28     }
    29 
    30     /*减法*/
    31     static void minus(CComplex &c1, CComplex &c2, CComplex &c3)
    32     {
    33         double _real = c1.getReal() - c2.getReal();
    34         double _img = c1.getImg() - c2.getImg();
    35         c3.setReal(_real);
    36         c3.setImg(_img);
    37     }
    38 
    39     /*乘法*/
    40     static void multi(CComplex &c1, CComplex &c2, CComplex &c3)
    41     {
    42 
    43         double a = c1.getReal();
    44         double b = c1.getImg();
    45         double c = c2.getReal();
    46         double d = c2.getImg();
    47 
    48         double _real = a * c - b * d;
    49         double _img = a * d + b * c;
    50         c3.setReal(_real);
    51         c3.setImg(_img);
    52     }
    53 
    54     double getModulus   ();    //模长计算
    55     double getAngle     ();    //幅角计算
    56 };
    CComplex.h
    /*
        复数类
    */
    #include "stdafx.h"
    #include "CComplex.h"
    
    
    /*构造函数和析构函数*/
    CComplex::CComplex()
    {
        this->m_real = 0;
        this->m_img = 0;
    
    }
    CComplex::CComplex(CComplex &c)
    {
        this->m_real = c.getReal();
        this->m_img = c.getImg();
    }
    CComplex::CComplex(double real, double img)
    {
        this->m_real = real;
        this->m_img = img;
    }
    CComplex::~CComplex()
    {
        this->m_real = 0;
        this->m_img = 0;
    }
    /* setters & getters */
    void CComplex::setReal(double value)
    {
        this->m_real = value;
    }
    double CComplex::getReal()
    {
        return this->m_real;
    }
    void CComplex::setImg(double value)
    {
        this->m_img = value;
    }
    double CComplex::getImg()
    {
        return this->m_img;
    }
    
    double CComplex::getModulus() 
    {
        return sqrt(m_real*m_real + m_img * m_img);
    }
    double CComplex::getAngle() 
    {
        double modulus = getModulus();
        if (modulus == 0) {
            return 0;
        }
        else 
        {
            return acos(m_real / modulus);
        }
    }
    CComplex.cpp

    fft计算类:

     1 #pragma once
     2 #include "CComplex.h"
     3 #include <math.h>
     4 #include <iostream>
     5 
     6 #define PI 3.141592654
     7 class CMyFFT
     8 {
     9 
    10 public:
    11     CMyFFT();
    12     ~CMyFFT();
    13     static void doFFT(int N, int m, CComplex *x, CComplex *X); /* FFT程序*/
    14     static void W_N_nk(int N, int n, int k, CComplex& factor); /* 计算旋转因子*/
    15 };
    CMyFFT.h
    #include "stdafx.h"
    #include "CMyFFT.h"
    
    
    
    CMyFFT::CMyFFT()
    {
    }
    
    
    CMyFFT::~CMyFFT()
    {
    }
    
    void CMyFFT::doFFT(int N, int m, CComplex *x, CComplex *X)
    {
        if (N != int(exp2(m + 1))) //检查输入参数
        {   
            exit(0);
            return;
        }
        if ((N != 2) && (m != 0)) /* 没到基2*/
        {
            /*
            准备存储空间
            */
            CComplex *ou = new CComplex[ N / 2 ];
            CComplex *ji = new CComplex[ N / 2 ];
            CComplex *Ak = new CComplex[ N / 2 ];
            CComplex *Bk = new CComplex[ N / 2 ];
            /*
            *奇偶分离
            */
            for (int i = 0; i < N;i++)
            {
                if (i % 2 == 0)
                {
                    ou[i / 2] = x[i];
                }
                else
                {
                    ji[i / 2] = x[i];
                }
            }
            //求出Ak 和 Bk
            doFFT(N / 2, m - 1, ou, Ak);
            doFFT(N / 2, m - 1, ji, Bk);
            for (int k = 0; k < N / 2; k++)
            {
                CComplex factor;
                W_N_nk(N, 1, k, factor);
                CComplex tmp;
                CComplex::multi(factor, Bk[k], tmp);
                CComplex::add(Ak[k], tmp, X[k]);//X[k] = Ak[k] + (factor*Bk[k]);
                CComplex::minus(Ak[k], tmp, X[k + N / 2]);//X[ k + N / 2 ]  = Ak[k] - (factor*Bk[k]);
    
            }
            delete[] ou;
            delete[] ji;
            delete[] Ak;
            delete[] Bk;
        }
        else
        {
            int r = 0;
            int k = 0;
            CComplex factor1;
            CComplex factor2;
            W_N_nk(N / 2, r, k, factor1);
            W_N_nk(N, 1, k, factor2);
            CComplex A_0;
            CComplex::multi(x[0], factor1, A_0);
            CComplex B_0;
            CComplex::multi(x[1], factor1, B_0);
            CComplex tmp;
            CComplex::multi(B_0, factor2, tmp);
            CComplex::add(A_0, tmp, X[0]);      //X[ 0     ] = A_0 + B_0*factor2;
            CComplex::minus(A_0, tmp, X[1]);    //X[ 0 + 1 ] = A_0 - B_0*factor2;
        }
    }
    
    
    void CMyFFT::W_N_nk(int N, int n, int k, CComplex& factor)
    {
        // W_N_nk = e^( -j*2*pi*n*k/N)
        // cos(-2*pi*n*k/N) + jsin(-2*pi*n*k/N)
        factor.setReal(cos(-2 * PI * n * k / N));
        factor.setImg(sin(-2 * PI * n * k / N));
    }
    CMyFFT.cpp

    测试代码:

     1 #include "CComplex.h"
     2 #include "CMyFFT.h "
     3 using namespace std;
     4 int main()
     5 {
     6     int m = 10;
     7     int N = int(exp2(m));
     8     CComplex x[1024];
     9     CComplex X[1024];
    10 
    11     for (int i = 0; i < N;i++) {
    12         x[i].setReal(i);
    13     }
    14     CMyFFT::doFFT(N, m-1, x, X);
    15 
    16 
    17     cout << "输出幅度值:" << endl;
    18     for (int i = 0; i < 20;i++) {
    19       cout << X[i].getModulus() <<endl;
    20     
    21     }
    22     cout << "输出相角值:" << endl;
    23     for (int i = 0; i < 20;i++) {
    24         cout << X[i].getAngle() << endl;
    25     }
    26     system("pause");
    27     return 0;
    28 }
    main.cpp

    测试结果与Matlab自带的fft函数一致.

    测试工程:

    VS2017 

    https://files.cnblogs.com/files/alimy/MyFFT_Cpp.zip

    ~不再更新,都不让我写公式,博客园太拉胯了
  • 相关阅读:
    ref与out的区别(C#)
    用MS SQL Server 2008修改数据库表时提示“不允许保存更改”的解决方法
    测试的职责
    性能测试新手误区(三):用户数与压力
    JAVA + LR实现apache流媒体的性能测试(LR部分)
    性能测试新手误区(二):为什么我模拟的百万测试数据是无效的
    JAVA + LR实现apache流媒体的性能测试(JAVA部分)
    性能测试新手误区(六):性能监控
    性能测试新手误区(五):这是性能问题么
    性能测试新手误区(四):一切来自录制
  • 原文地址:https://www.cnblogs.com/alimy/p/9104214.html
Copyright © 2011-2022 走看看