<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
我們在進行訊號分析的時候,難免會使用到複數。但是遺憾的是,C#沒有自帶的複數類,以下提供了一種複數類的構建方法。
複數相比於實數,可以理解為一個二維數,構建複數類,我們需要實現以下這些內容:
C#實現的程式碼如下:
public class Complex { double real; double imag; public Complex(double x, double y) //建構函式 { this.real = x; this.imag = y; } //通過屬性實現對複數實部與虛部的單獨檢視和設定 public double Real { set { this.real = value; } get { return this.real; } } public double Imag { set { this.imag = value; } get { return this.imag; } } //過載加法 public static Complex operator +(Complex c1, Complex c2) { return new Complex(c1.real + c2.real, c1.imag + c2.imag); } public static Complex operator +(double c1, Complex c2) { return new Complex(c1 + c2.real, c2.imag); } public static Complex operator +(Complex c1, double c2) { return new Complex(c1.Real + c2, c1.imag); } //過載減法 public static Complex operator -(Complex c1, Complex c2) { return new Complex(c1.real - c2.real, c1.imag - c2.imag); } public static Complex operator -(double c1, Complex c2) { return new Complex(c1 - c2.real, -c2.imag); } public static Complex operator -(Complex c1, double c2) { return new Complex(c1.real - c2, c1.imag); } //過載乘法 public static Complex operator *(Complex c1, Complex c2) { double cr = c1.real * c2.real - c1.imag * c2.imag; double ci = c1.imag * c2.real + c2.imag * c1.real; return new Complex(Math.Round(cr, 4), Math.Round(ci, 4)); } public static Complex operator *(double c1, Complex c2) { double cr = c1 * c2.real; double ci = c1 * c2.imag; return new Complex(Math.Round(cr, 4), Math.Round(ci, 4)); } public static Complex operator *(Complex c1, double c2) { double cr = c1.Real * c2; double ci = c1.Imag * c2; return new Complex(Math.Round(cr, 4), Math.Round(ci, 4)); } //過載除法 public static Complex operator /(Complex c1, Complex c2) { if (c2.real == 0 && c2.imag == 0) { return new Complex(double.NaN, double.NaN); } else { double cr = (c1.imag * c2.imag + c2.real * c1.real) / (c2.imag * c2.imag + c2.real * c2.real); double ci = (c1.imag * c2.real - c2.imag * c1.real) / (c2.imag * c2.imag + c2.real * c2.real); return new Complex(Math.Round(cr, 4), Math.Round(ci, 4)); //保留四位小數後輸出 } } public static Complex operator /(double c1, Complex c2) { if (c2.real == 0 && c2.imag == 0) { return new Complex(double.NaN, double.NaN); } else { double cr = c1 * c2.Real / (c2.imag * c2.imag + c2.real * c2.real); double ci = -c1 * c2.imag / (c2.imag * c2.imag + c2.real * c2.real); return new Complex(Math.Round(cr, 4), Math.Round(ci, 4)); //保留四位小數後輸出 } } public static Complex operator /(Complex c1, double c2) { if (c2 == 0) { return new Complex(double.NaN, double.NaN); } else { double cr = c1.Real / c2; double ci = c1.imag / c2; return new Complex(Math.Round(cr, 4), Math.Round(ci, 4)); //保留四位小數後輸出 } } //建立一個取模的方法 public static double Abs(Complex c) { return Math.Sqrt(c.imag * c.imag + c.real * c.real); } //建立一個取相位角的方法 public static double Angle(Complex c) { return Math.Round(Math.Atan2(c.real, c.imag), 6);//保留6位小數輸出 } //過載字串轉換方法,便於顯示覆數 public override string ToString() { if (imag >= 0) return string.Format("{0}+i{1}", real, imag); else return string.Format("{0}-i{1}", real, -imag); } //尤拉公式 public static Complex Exp(Complex c) { double amplitude = Math.Exp(c.real); double cr = amplitude * Math.Cos(c.imag); double ci = amplitude * Math.Sin(c.imag); return new Complex(Math.Round(cr, 4), Math.Round(ci, 4));//保留四位小數輸出 } }
以下的遞迴法是基於奇偶分解實現的。
奇偶分解的原理推導如下:
x(2r)和x(2r+1)都是長度為N/2−1的資料序列,不妨令
則原來的DFT就變成了:
於是,將原來的N點傅立葉變換變成了兩個N/2點傅立葉變換的線性組合。
但是,N/2點傅立葉變換隻能確定N/2個頻域資料,另外N/2個資料怎麼確定呢?
因為X1(k)和X2(k)週期都是N/2,所以有
從而得到:
綜上,我們就可以得到遞迴法實現FFT的流程:
1.對於每組資料,按奇偶分解成兩組資料
2.兩組資料分別進行傅立葉變換,得到X1(k)和X2(k)
3.總體資料的X(k)由下式確定:
4.對上述過程進行遞迴
具體程式碼實現如下:
public Complex[] FFTre(Complex[] c) { int n = c.Length; Complex[] cout = new Complex[n]; if (n == 1) { cout[0] = c[0]; return cout; } else { double n_2_f = n / 2; int n_2 = (int)Math.Floor(n_2_f); Complex[] c1 = new Complex[n / 2]; Complex[] c2 = new Complex[n / 2]; for (int i = 0; i < n_2; i++) { c1[i] = c[2 * i]; c2[i] = c[2 * i + 1]; } Complex[] c1out = FFTre(c1); Complex[] c2out = FFTre(c2); Complex[] c3 = new Complex[n / 2]; for (int i = 0; i < n / 2; i++) { c3[i] = new Complex(0, -2 * Math.PI * i / n); } for (int i = 0; i < n / 2; i++) { c2out[i] = c2out[i] * Complex.Exp(c3[i]); } for (int i = 0; i < n / 2; i++) { cout[i] = c1out[i] + c2out[i]; cout[i + n / 2] = c1out[i] - c2out[i]; } return cout; } }
順便提供幾個常用的窗函數:
public class WDSLib { //以下窗函數均為periodic public double[] Rectangle(int len) { double[] win = new double[len]; for (int i = 0; i < len; i++) { win[i] = 1; } return win; } public double[] Bartlett(int len) { double length = (double)len - 1; double[] win = new double[len]; for (int i = 0; i < len; i++) { if (i < len / 2) { win[i] = 2 * i / length; } else { win[i] = 2 - 2 * i / length; } } return win; } public double[] Hamming(int len) { double[] win = new double[len]; for (int i = 0; i < len; i++) { win[i] = 0.54 - 0.46 * Math.Cos(Math.PI * 2 * i / len); } return win; } public double[] Hanning(int len) { double[] win = new double[len]; for (int i = 0; i < len; i++) { win[i] = 0.5 * (1 - Math.Cos(2 * Math.PI * i / len)); } return win; } public double[] Blackman(int len) { double[] win = new double[len]; for (int i = 0; i < len; i++) { win[i] = 0.42 - 0.5 * Math.Cos(Math.PI * 2 * (double)i / len) + 0.08 * Math.Cos(Math.PI * 4 * (double)i / len); } return win; } }
以上就是C#實現FFT(遞迴法)的範例程式碼的詳細內容,更多關於C# FFT遞迴法的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45