6

我正在编写一个非常简单的就地 DFT。我正在使用此处显示的公式: http ://en.wikipedia.org/wiki/Discrete_Fourier_transform#Definition以及欧拉公式,以避免为此使用复数类。到目前为止,我有这个:

private void fft(double[] data)
        {
            double[] real = new double[256];
            double[] imag = new double[256];
            double pi_div_128 = -1 * Math.PI / 128;
            for (int k = 0; k < 256; k++)
            {
                for (int n = 0; n < 256; n++)
                {
                    real[k] += data[k] * Math.Cos(pi_div_128 * k * n);
                    imag[k] += data[k] * Math.Sin(pi_div_128 * k * n);
                }
                data[k] = Math.Sqrt(real[k] * real[k] + imag[k] * imag[k]);
            }
        }

但是 Math.Cos 和 Math.Sin 项最终会变成正数和负数,所以当我将这些项与 data[k] 相乘时,它们会抵消,我只会得到一些非常小的值。我知道它是如何发生的,但我无法理解我的代码可能如何错误地表示数学。任何帮助表示赞赏。仅供参考,我必须自己写,我意识到我可以得到现成的 FFT。

4

2 回答 2

9

我相信您在本节中有错误

for (int n = 0; n < 256; n++)
{
    real[k] += data[k] * Math.Cos(pi_div_128 * k * n);
    imag[k] += data[k] * Math.Sin(pi_div_128 * k * n);
}

您应该将 data[k] 替换为 data[n]

编辑:

您还在以下行中破坏您的数据:

data[k] = Math.Sqrt(real[k] * real[k] + imag[k] * imag[k]);

您必须将复数的模数存储在其他地方或以后。如果模数是你想要的,并且你想将它存储在 data[] 中,你必须在计算变换后编写另一个循环。整个 data[] 是计算每个 real[k] 和 imag [k] 所必需的。

于 2010-04-28T02:15:24.187 回答
8
private double[] dft(double[] data)
{
    int n = data.Length;
    int m = n;// I use m = n / 2d;
    double[] real = new double[n];
    double[] imag = new double[n];
    double[] result = new double[m];
    double pi_div = 2.0 * Math.PI / n;
    for (int w = 0; w < m; w++)
    {
        double a = w * pi_div;
        for (int t = 0; t < n; t++)
        {
            real[w] += data[t] * Math.Cos(a * t);
            imag[w] += data[t] * Math.Sin(a * t);
        }
        result[w] = Math.Sqrt(real[w] * real[w] + imag[w] * imag[w]) / n;
    }
    return result;
}
于 2012-08-15T20:23:22.133 回答