Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >快速傅里叶变换C++递归算法实现

快速傅里叶变换C++递归算法实现

作者头像
Florian
发布于 2018-02-05 02:42:54
发布于 2018-02-05 02:42:54
2.1K0
举报
文章被收录于专栏:技术点滴技术点滴

快速傅里叶变换C++递归算法实现

网上有些算法资料经测试运行结果是错误的,虽然代码的使用的是非递归形式。为了方便验证快速傅里叶变换的准确性,我提供了自己设计的递归算法。

基于时域抽取的“基2”快速傅里叶变换算法代码:

    Fouier.h文件:

代码语言:js
AI代码解释
复制
#pragma once
#include"Complex.h"
class Fouier
{
    Complex * data;
 void fft(int start,int step,int len);
    Complex W(int k,int n);//e^(-i*2*pi*k/n)
public:
    Fouier(void);
    ~Fouier(void);
 
 void fft();
};

    Fouier.c文件:

代码语言:js
AI代码解释
复制
#include "Fouier.h"
#include<iostream>
using namespace std;
#include<cmath>
#include<ctime>
#define DATALEN 32
#define KEYVALUE 10000 //生成随机浮点数的值,保证分子和分母在这个值之内
#define PI 3.14159265358979323846
Fouier::Fouier(void)
{
    data=new Complex[DATALEN];
    srand(unsigned int(time(0)));
    cout<<"源数据:"<<endl;
 for(int i=0;i<DATALEN;i++)
    {
        data[i]=(rand()%(KEYVALUE))/(double)(rand()%(KEYVALUE)+1);
 if(i%5==0&&i!=0)
            cout<<endl;
        cout<<data[i]<<" ";
    }
    cout<<endl;
}


Fouier::~Fouier(void)
{
    delete [] data;
}
Complex Fouier:: W(int k,int n)//欧拉公式
{
 double alpha=-2*PI*k/n;
 return Complex(cos(alpha),sin(alpha));
}
void Fouier::fft(int start,int step,int len)
{
 if(len==1)//一个元素
    {
 //一个元素不需要变换
 return ;
    }
    fft(start,step*2,len/2);//X1(k)
    fft(start+step,step*2,len/2);//X2(k)
    Complex X1,X2;
 for(int i=0;i<len/2;i++)
    {
        X1=data[start+step*i*2];
        X2=data[start+step*(i*2+1)];
 //计算X(k):k=0~N/2-1
        data[start+step*i]=X1+W(i,len)*X2;
 //计算X(k):k=N/2~N-1
        data[start+step*(i+len/2)]=X1-W(i,len)*X2;
    }
}
void Fouier::fft()
{
    fft(0,1,DATALEN);
    cout<<"变换后数据:"<<endl;
 for(int i=0;i<DATALEN;i++)
    {
 if(i%5==0&&i!=0)
            cout<<endl;
        cout<<data[i]<<" ";
    }
}

Complex.h文件:

代码语言:js
AI代码解释
复制
#pragma once
#include<iostream>
using namespace std;
class Complex//a+b*i
{
 double a;//实数部分
 double b;//虚数部分
public:
    Complex(double a=0,double b=0);
 //+操作
    friend Complex operator +(Complex &x,Complex &y);
    friend Complex operator +(double x,Complex &y);
    friend Complex operator +(Complex &x,double y);
 //-操作
    friend Complex operator -(Complex &x,Complex &y);
    friend Complex operator -(double x,Complex &y);
    friend Complex operator -(Complex &x,double y);
 //*操作
    friend Complex operator *(Complex &x,Complex &y);
    friend Complex operator *(double x,Complex &y);
    friend Complex operator *(Complex &x,double y);
 //=操作
    Complex operator =(Complex &x);
    Complex operator =(double x);
 //<<操作
    friend ostream & operator<<(ostream&out,Complex&c);

    ~Complex(void);
};
代码语言:js
AI代码解释
复制

    Complex.c文件:
#include "Complex.h"

Complex::Complex(double a,double b)//虚部默认是0
{
 this->a=a;
 this->b=b;
}


Complex::~Complex(void)
{
}

Complex operator +(Complex &x,Complex &y)
{
 return Complex(x.a+y.a,x.b+y.b);
}
Complex operator +(double x,Complex &y)
{
 return Complex(x+y.a,y.b);
}
Complex operator +(Complex &x,double y)
{
 return Complex(x.a+y,x.b);
}

Complex operator -(Complex &x,Complex &y)
{
 return Complex(x.a-y.a,x.b-y.b);
}
Complex operator -(double x,Complex &y)
{
 return Complex(x-y.a,-y.b);
}
Complex operator -(Complex &x,double y)
{
 return Complex(x.a-y,x.b);
}

Complex operator *(Complex &x,Complex &y)
{
 return Complex(x.a*y.a-x.b*y.b,x.a*y.b+x.b*y.a);
}
Complex operator *(double x,Complex &y)
{
 return Complex(x*y.a,x*y.b);
}
Complex operator *(Complex &x,double y)
{
 return Complex(x.a*y,x.b*y);
}

Complex Complex::operator =(Complex &x)
{
    a=x.a;
    b=x.b;
 return *this;
}
Complex Complex::operator =(double x)
{
    a=x;
    b=0;
 return *this;
}
ostream & operator<<(ostream&out,Complex&c)
{
 if(c.a!=0||c.a==0&&c.b==0)
 out<<c.a;
 if(c.b!=0)
    {
 if(c.b>0)
 out<<"+";
 if(c.b!=1)
 out<<c.b;
 out<<"i";
    }
 return out;
}

    main.c文件:

代码语言:js
AI代码解释
复制
#include<iostream>
using namespace std;
#include"Fouier.h"

int main()
{
    Fouier f;
    f.fft();
 return 0;
}

    如有错误,欢迎批评指正!

    参考资料:http://zhoufazhe2008.blog.163.com/blog/static/63326869200971010421361/

       维基百科:http://zh.wikipedia.org/wiki/%E5%BF%AB%E9%80%9F%E5%82%85%E7%AB%8B%E5%8F%B6%E5%8F%98%E6%8D%A2

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2012-07-28 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
C++之运算符重载(二)
https://blog.csdn.net/zy010101/article/details/105240318
zy010101
2020/04/08
4240
C++之运算符重载(二)
C++ Primer Plus习题及答案-第十一章
成员函数是类定义的一部分,通过特定的对象来调用。成员函数可以隐式访问调用对象的成员,而无需使用成员运算符。友元函数不是类的组成部分,因此被称为直接函数调用。友元函数不能隐式访问类成员,而需要将成员运算符用作参数传递的对象。
艰默
2022/12/04
7190
C++ Primer Plus习题及答案-第十一章
快速傅里叶变换
快速傅里叶变换(FFT)是实现离散傅里叶变换(DFT)和离散傅里叶逆变换(IDFT)的快速算法,其时间复杂度为 。DFT 在实际生活中有很多应用,比如通过离散傅里叶变换,可以将系数表示的多项式转为点值表示的多项式,从而使得多项式的乘法的复杂度由 降为 。
hotarugali
2022/03/09
4800
C++之运算符重载(一)
C++支持运算符重载。运算符重载的好处是使得使用类的人更加方便。设计类的人只不过是把设计函数变成了设计运算符重载。因此,运算符重载的本质仍旧是一个函数。
zy010101
2020/04/08
4650
C++之运算符重载(一)
C++中与类有关的注意事项(更新中~~~)
当然了,首先调用基类的构造函数是不容置疑的,不管它在哪里,记住即可,不过关于对象成员的构造函数的调用还需注意, 见 L1, L2, L3, 它们的构造函数的调用次序与它们在此的相对次序有关,如类A排在第一行,因此先调用关于它的对象,这里还应再注意一点,尽管先定义了它的对象成员,不过它不会立即调用其默认构造函数,而是去看看你有没有写相应的初始化(注意:这里是指在类里面,而不是指main函数内以及类外函数,对于类外函数应注意,在定义类的同时必须给它附上一定的值,不过这根据需要而定,如果你已经设置了无参构造函数了或者你在类内定义了一些set函数),比如调用完基类构造函数后优先调用a0的构造函数,但初始化列表中并没有它,故调用它的默认构造函数,然后调用a4的构造函数,依此类推,就不难理解编译运行后的结果了。
_DIY
2019/09/11
7390
C++中与类有关的注意事项(更新中~~~)
C++函数模板(模板函数)详解
大家好,又见面了,我是你们的朋友全栈君。 C++函数模板(模板函数)详解 定义 用法: 函数模板的原理 延申用法 2.1为什么需要类模板 2.2单个类模板语法 2.3继承中的类模板语法 案例1: 案例2: 2.4类模板的基础语法 2.5类模板语法知识体系梳理 1.所有的类模板函数写在类的内部 复数类: 2.所有的类模板函数写在类的外部,在一个cpp中 2.5总结 关于类模板的几点说明: 2.6类模板中的static关键字 案例2:以下来自:C++类模板遇上static关键字 2.7类模板在项目开发中的
全栈程序员站长
2022/07/22
1.9K0
C++函数模板(模板函数)详解
模拟EXCEL排序 c++ sort排序 多重排序 题解
题目链接: https://pta.patest.cn/pta/test/15/exam/4/question/864附录有strcmp函数使用以及多重sort的解析.
十四君
2019/11/28
1.2K0
C++之操作符重载学习总结(二)
在上一篇文章里面我们已经提到了操作符重载的概念和使用,同时也举例了一个数学里面的复数操作,从一开始使用友元到使用操作符重载全局函数,再到使用操作符重载类成员函数,这样一步步演变而成我们最终实现了复数的实部加实部,虚部加虚部;而且当时我们只讲解了一个操作重载符“+”,所以为了完善学习体系,咋们今天继续把剩下的操作重载符总结完,以免知识体系零零散散。那么复数完善的操作符还有那些呢,其实很简单就能能想到,和对数学里面的实数操作一样,加减乘除肯定是少不了嘛,下面是汇总的操作符总结:
用户6280468
2022/03/21
2750
运算符重载
流操作符>>,<<一般使用非成员函数实现,也就是友元函数实现,这样可以符合程序员的惯性思维
DeROy
2020/05/11
9880
C++ 自定义数组类模板
本篇通过自定义数组类模板,实现python列表的绝大部分函数,包括: 求最大值 求最小值 排序 在尾部添加元素 在指定位置(默认尾部)删除元素 在指定位置插入元素 在尾部添加进另外一个数组 查找指定值 移除第一次出现的指定值 从尾到头反向排列 切片功能 两个数组相等的判断 列表的数乘复制 等等 以及numpy中的arange函数 涉及到的知识点有: 类模板 函数模板 友元函数模板的类外实现 运算符重载(==, !=, *, +, <<, []) 头文件myArray.hpp代码如下: #
用户6021899
2021/07/05
1.2K0
C++ 自定义复数类
C++练习。 功能:自定义复数类型,实现复数的加、减、乘、除、求共轭复数、乘方、开方等运算。 涉及到的基础知识点有: 运算符重载(+,-,*,/, <<, ^, ==, != 等运算符的重载) 友元函数(友元函数可访问类的私有属性) 函数返回指向数组的指针。此例中数组的元素是类的对象。 左值引用与右值引用 主动抛出异常(使用关键字throw) #include <iostream> #include <cmath> using namespace std; class Division_by_zer
用户6021899
2021/05/20
1.4K0
快速傅里叶变换(FFT)详解
本文只讨论FFT在信息学奥赛中的应用 文中内容均为个人理解,如有错误请指出,不胜感激 前言 先解释几个比较容易混淆的缩写吧 DFT:离散傅里叶变换—> 计算多项式乘法 FFT:快速傅里叶变换—> 计算多项式乘法 FNTT/NTT:快速傅里叶变换的优化版—>优化常数及误差 FWT:快速沃尔什变换—>利用类似FFT的东西解决一类卷积问题 MTT:毛爷爷的FFT—>非常nb 多项式 系数表示法 设A(x)表示一个n-1次多项式 则 例如: 利用这种方法计算多项式乘法复杂度为 (第一个多项式中
attack
2018/04/11
4K2
快速傅里叶变换(FFT)详解
大学C++课程提炼概括【C++笔记】
如果未写明限制幅(public: private: protected: )则默认为私有
来杯Sherry
2023/05/25
4130
sort 排序
sort(开始地址,结束地址,排序方式),其中第三参数可以没有,则默认为升序排序。
Cell
2022/02/24
1.2K0
C++基础整理
字符串变量:字符串是以空字符'\0'结束的字符数组,空字符'\0'自动添加到字符串的内部表示中。在声明字符串变量的时候,应该为这个空结束符预留一个额外元素空间。
算法之名
2022/03/24
7580
HDU-6004-Periodical Cicadas
该文是有关期刊论文摘要总结的示例。
f_zyj
2018/01/09
4480
HDU-6004-Periodical Cicadas
C++-入门语法(五)
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
cwl_java
2019/10/28
3340
C++查缺补漏
本文总结了几乎所有不易理解或是容易忘记的C++知识,可作为手册查阅,内容参考自清华大学郑莉教授的C++课程。
luxuantao
2021/02/20
2.6K0
离散傅里叶变换
离散傅里叶变换 #include<iostream> #include<math.h> using namespace std; #define PI 3.14159265354 struct complex{ double r,i; }; complex multi(complex a,complex b){ complex tmp; tmp.r=a.r*b.r-a.
Pulsar-V
2018/04/18
1.2K0
「c++小学期」实验题目及代码
面向对象编程的C++,和平时做题用的C++还是有差距的。实验的题目都是小题目,就都做一下吧。
饶文津
2020/06/02
1.3K0
「c++小学期」实验题目及代码
相关推荐
C++之运算符重载(二)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档