FFT算法学习心得
来源:互联网 发布:ug10安装java虚拟机 编辑:程序博客网 时间:2024/06/05 20:59
1。通常的FFT算法: 直接计算离散傅立叶变换具有n^2的复杂度,而cooley 和tukey在1965年发现了一种计算离散傅立叶变换的快速算法(即通常所说的FFT算法),这个算法在计算变换长度n=2^k的离散傅立叶变换时,具有 n*k 的复杂度,即O(n)=n*log2(n), 下面以此为例,讲讲快FFT的特点。
1)复数运算:傅立叶变换是基于复数的,因此首先知道复数的运算规则,在FFT算法中,只涉及复数的加、减和乘法三种运算。一个复数可表示为 c=( x,yi), x 为复数的实部,y为复数的虚部,i为虚数单位,等于-1的平方根。复数的运算规则是:若c1 表示为 (x1,y1),c2 表示为(x2,y2), 则 (x1+x2,y1+y2)和(x1-x2,y1-y2)分别等于c1+c2的和,c1-c2的差,复数的乘法相对复杂一些,c1*c2 的积为 (x1*x2-y1*y2,x1*y2+x2*y1).
2)蝶形变换:普通的FFT算法称为基2的FFT算法,这种算法的核心是蝶形变换 长度为n=2^k1的变换共需要做 k1 * n/2 次蝶形变换,若需变换数据表示为一个复数数组c[],则每次蝶形变换有2个输入 c[i],c[i+s],两个输出:c[i],c[i+s],s成为翅间距。 每个变换的基本算法是:
t=wr * c[i+s];
c[i+s]=c[i]-t;
c[i]=c[i]+t;
前面说过,长度为n=2^k1的变换共需要做 k1 * n/2次变换,实际的程序是一个3层循环,共需要k1*k2*(k3/2)次变换(k2*k3/2=n/2)。前面的wr是w的整数次方,w=e^(-2*PI/k3) (k3=2,4,8,16...n,PI是圆周率),也成为旋转因子,例如n=32的变换需要log2(32)=5趟变换:
第1趟变换需要16*1次变换,翅间距是1, 若w=e^(-2*PI/2), 则wr=w^1
第2趟变换需要8*2次变换, 翅间距是2, 若w=e^(-2*PI/4), 则wr=w^1,w^2
第3趟变换需要4*2次变换, 翅间距是4, 若w=e^(-2*PI/8), 则wr=w^1,w^2,w^3,w^4
第4趟变换需要2*8次变换, 翅间距是8, 若w=e^(-2*PI/16),则wr=w^1,w^2,w^3,w^4,w^5,w^6,w^7,w^8
第5趟变换需要16*1次变换,翅间距是16, 若w=e^(-2*PI/32),则wr=w^1,w^2,w^3,w^4,w^5...w^15,w^16
3)w数组,w 的实部=cos(2*PI/k3),w的虚部= -sin(2*PI/k3),计算出w,则wr数组就好求了,不断即相乘即可,当然也可以通过三角函数直接求。w^p 的实部=cos(2*PI/K3*p),虚部=-sin(2*PI/k3*p)
4)复数数组排序,在基2的蝶形变换中,复数数组需要重新排序,c[i] 要放置到数组c的第 reverse(c[i]) 的位置,m=reverse(n) 函数的算法是这样的,若 n的 k位2进制的为b[], b[k-1],B[k-2],...b[2],b[1],b[0],( b[i] 等于1或者0,b[0]为最低bit). 则m=reverse(n)的2进制的为 b[0],b[1],b[2],b[3],...b[k-1] (b[k-1]为最低bit).
2.更复杂的变换算法:基2的蝶形变换算法不止一种,它可分为2类,一类为基2时分傅立叶变换,另一类为基2频分傅立叶变换。上例的变为基2时分算法,在每一趟变换中,翅间距依次变大,第一趟为2,最后一趟为n/2,数组重排在变换之前进行,基2频分算法正好相反,翅间距依次缩小,起于n/2,止于2,数组重排在蝶形变换之后进行。 在<傅立叶变换>一书中,提到3种基2时分变换,3种基2频分变换。上述算法称为基2时分FFT第二种算法。我在看你的这个程序的同时,还看到朱志刚写的一个FFT程序,这个程序的算法是基2时分FFT第一种算法,它比经典的算法更复杂,需要对wr数组进行逆序排列。
3.更复杂的FFT算法,除了基2 的FFT算法外,还有更加复杂的基4算法,基8算法,甚至基3,基5算法,纯粹的基4算法只能计算长度为4^k的变换,但它比基2的算法速度更高。为了提高 速度,很多FFT算法使用混合基算法。关于混合基FFT算法我还在学习中,希望有高手给予帮助。
1)复数运算:傅立叶变换是基于复数的,因此首先知道复数的运算规则,在FFT算法中,只涉及复数的加、减和乘法三种运算。一个复数可表示为 c=( x,yi), x 为复数的实部,y为复数的虚部,i为虚数单位,等于-1的平方根。复数的运算规则是:若c1 表示为 (x1,y1),c2 表示为(x2,y2), 则 (x1+x2,y1+y2)和(x1-x2,y1-y2)分别等于c1+c2的和,c1-c2的差,复数的乘法相对复杂一些,c1*c2 的积为 (x1*x2-y1*y2,x1*y2+x2*y1).
2)蝶形变换:普通的FFT算法称为基2的FFT算法,这种算法的核心是蝶形变换 长度为n=2^k1的变换共需要做 k1 * n/2 次蝶形变换,若需变换数据表示为一个复数数组c[],则每次蝶形变换有2个输入 c[i],c[i+s],两个输出:c[i],c[i+s],s成为翅间距。 每个变换的基本算法是:
t=wr * c[i+s];
c[i+s]=c[i]-t;
c[i]=c[i]+t;
前面说过,长度为n=2^k1的变换共需要做 k1 * n/2次变换,实际的程序是一个3层循环,共需要k1*k2*(k3/2)次变换(k2*k3/2=n/2)。前面的wr是w的整数次方,w=e^(-2*PI/k3) (k3=2,4,8,16...n,PI是圆周率),也成为旋转因子,例如n=32的变换需要log2(32)=5趟变换:
第1趟变换需要16*1次变换,翅间距是1, 若w=e^(-2*PI/2), 则wr=w^1
第2趟变换需要8*2次变换, 翅间距是2, 若w=e^(-2*PI/4), 则wr=w^1,w^2
第3趟变换需要4*2次变换, 翅间距是4, 若w=e^(-2*PI/8), 则wr=w^1,w^2,w^3,w^4
第4趟变换需要2*8次变换, 翅间距是8, 若w=e^(-2*PI/16),则wr=w^1,w^2,w^3,w^4,w^5,w^6,w^7,w^8
第5趟变换需要16*1次变换,翅间距是16, 若w=e^(-2*PI/32),则wr=w^1,w^2,w^3,w^4,w^5...w^15,w^16
3)w数组,w 的实部=cos(2*PI/k3),w的虚部= -sin(2*PI/k3),计算出w,则wr数组就好求了,不断即相乘即可,当然也可以通过三角函数直接求。w^p 的实部=cos(2*PI/K3*p),虚部=-sin(2*PI/k3*p)
4)复数数组排序,在基2的蝶形变换中,复数数组需要重新排序,c[i] 要放置到数组c的第 reverse(c[i]) 的位置,m=reverse(n) 函数的算法是这样的,若 n的 k位2进制的为b[], b[k-1],B[k-2],...b[2],b[1],b[0],( b[i] 等于1或者0,b[0]为最低bit). 则m=reverse(n)的2进制的为 b[0],b[1],b[2],b[3],...b[k-1] (b[k-1]为最低bit).
2.更复杂的变换算法:基2的蝶形变换算法不止一种,它可分为2类,一类为基2时分傅立叶变换,另一类为基2频分傅立叶变换。上例的变为基2时分算法,在每一趟变换中,翅间距依次变大,第一趟为2,最后一趟为n/2,数组重排在变换之前进行,基2频分算法正好相反,翅间距依次缩小,起于n/2,止于2,数组重排在蝶形变换之后进行。 在<傅立叶变换>一书中,提到3种基2时分变换,3种基2频分变换。上述算法称为基2时分FFT第二种算法。我在看你的这个程序的同时,还看到朱志刚写的一个FFT程序,这个程序的算法是基2时分FFT第一种算法,它比经典的算法更复杂,需要对wr数组进行逆序排列。
3.更复杂的FFT算法,除了基2 的FFT算法外,还有更加复杂的基4算法,基8算法,甚至基3,基5算法,纯粹的基4算法只能计算长度为4^k的变换,但它比基2的算法速度更高。为了
- FFT算法学习心得
- FFT & NTT学习心得
- FFT算法
- FFT算法
- FFT算法
- FFT算法
- FFT算法
- FFT算法
- fft的递归算法
- FFT 算法实现
- FFT蝶形算法,IFFT
- 【例程】MSP430 FFT算法
- FFT算法整理[转载]
- FFT算法应用实例
- C#的FFT算法
- FFT算法实现
- 自己实现FFT算法
- FFT算法详解
- 如何杀掉带锁的Oracle进程
- 如何创建Filter的属性页
- 房地产广告——俗的有理由
- div+css实现Firefox与IE6兼容的手形鼠标指针
- 用户必备资料 103个Windows XP运行命令
- FFT算法学习心得
- Rhythmbox mp3 support
- Java入门所需的30个概念
- 如何提高日语听力水平
- VS2005项目的安装与布署
- JSP环境配置问题
- 35岁前程序员要规划好的四件事
- ASP.NET中生成条形码
- C#检测含有中文字符串的实际长度