简单的就地离散傅立叶变换(DFT)

时间:2010-04-28 02:06:08

标签: c# fft

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

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术语最终都是正面和负面的,所以当我添加这些术语乘以数据[k]时,它们会被取消,我只会得到一些极小的值。我看到它是如何发生的,但是我无法理解我的代码是如何错误地代表数学的。任何帮助表示赞赏。仅供参考,我必须自己编写,我知道我可以使用现成的FFT。

2 个答案:

答案 0 :(得分: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);
}

您应该将数据[k]替换为数据[n]

修改

你也在破坏你的数据:

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

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

答案 1 :(得分:7)

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;
}