为了自己的学习,我正在尝试用C#实现这里描述的FFT算法:
https://en.wikipedia.org/wiki/Cooley%E2%80%93Tukey_FFT_algorithm
在“数据重新排序,位反转和就地算法”下。
我的代码如下,“ cplx”结构具有一些后台运算符重载,以允许我对这些对象进行算术运算。
Bitreverse似乎工作正常,“旋转因子”计算也是如此,因此我不确定哪里出了问题。该代码看起来与Wiki页面上给出的伪代码非常相似。
public cplx[] FFT(cplx[] x)
{
//Bitreverse Copy
cplx[] a = BitReverse(x);
//Number of points
int n = a.Length;
for (int s = 1; s <= Math.Log(n); s++)
{
int m = (int)Math.Pow(2,s);
cplx w_m = Omega(m);
for (int k = 0; k < n; k += m)
{
cplx w = new cplx(1, 0);
for(int j = 0; j < m/2; j++)
{
cplx t = w * a[k + j + (m / 2)];
cplx u = a[k + j];
a[k + j] = u + t;
a[k + j + (m / 2)] = u - t;
w = w * w_m;
}
}
}
return a;
}
我正在使用具有8个样本的原点脉冲输入数组进行测试,这应该产生恒定的输出。
相反,我依次得到4个1和4个0。
顺便说一句,我假设在伪代码中:
for k = 0 to n-1 by m
引用for(k = 0; k < n; k += m)
,尽管我不确定这是正确的。
希望有人可以阐明我的无能!
干杯。
这是位反转和omega计算的代码。
private int Rev(int x, int k)
{
int reversed = 0;
for (int i = 0; i < k; i++)
{
reversed |= (x & (1 << i)) != 0 ? 1 << (k - 1 - i) : 0;
}
return reversed;
}
public cplx[] BitReverse(cplx[] x)
{
cplx[] r = new cplx[x.Length];
int bits = (int)Math.Log(x.Length, 2);
for(int k = 0; k < x.Length; k++)
{
r[Rev(k, bits)] = x[k];
}
return r;
}
private cplx Omega(int m)
{
float x = (- 2 * (float)Math.PI) / m;
return new cplx((float)Math.Cos(x), (float)(Math.Sin(x)));
}
答案 0 :(得分:1)
认为我已经解决了它,我在使用Math.Log()时应该一直使用log2(n)。
知道这有点愚蠢。