此傅立叶变换实现有什么问题

| 我正在尝试实现离散的傅立叶变换,但是没有用。我可能在某个地方写了一个错误,但是我还没有找到它。 根据以下公式: 该函数执行第一个循环,循环到X0-Xn-1 ...
    public Complex[] Transform(Complex[] data, bool reverse)
    {
        var transformed = new Complex[data.Length];
        for(var i = 0; i < data.Length; i++)
        {
            //I create a method to calculate a single value
            transformed[i] = TransformSingle(i, data, reverse);
        }
        return transformed;
    }
和实际的计算,这可能是错误所在。
    private Complex TransformSingle(int k, Complex[] data, bool reverse)
    {
        var sign = reverse ? 1.0: -1.0;
        var transformed = Complex.Zero;
        var argument = sign*2.0*Math.PI*k/data.Length;
        for(var i = 0; i < data.Length; i++)
        {
            transformed += data[i]*Complex.FromPolarCoordinates(1, argument*i);
        }
        return transformed;
    }
接下来是其余代码的说明:
var sign = reverse ? 1.0: -1.0;
反向DFT的参数中不包含
-1
,而常规DFT的参数中不包含
-1
var argument = sign*2.0*Math.PI*k/data.Length;
是算法的参数。这部分: 然后最后一部分
transformed += data[i]*Complex.FromPolarCoordinates(1, argument*i);
我想我已经仔细复制了算法,所以看不到我在哪里犯了错误... 附加信息 正如亚当·格里特(Adam Gritt)在回答中所显示的那样,AForge.net很好地实现了该算法。通过复制他们的代码,我大概可以在30秒内解决此问题。但是,我仍然不知道我在实现中做错了什么。 我真的很好奇我的缺点在哪里,我解释错了什么。
已邀请:
我现在从事复杂数学工作的日子现在落后于我,因此我自己可能会丢失一些东西。但是,在我看来,您正在执行以下行:
transformed += data[i]*Complex.FromPolarCoordinates(1, argument*i);
什么时候应该更像是:
transformed += data[i]*Math.Pow(Math.E, Complex.FromPolarCoordinates(1, argument*i));
除非您将其包裹在方法ѭ9中 更新: 我在AForge.NET Framework库中找到了以下代码,它显示了您的代码中未处理的其他Cos / Sin操作正在执行。可以在Sources \\ Math \\ FourierTransform.cs:DFT方法的完整上下文中找到此代码。
for ( int i = 0; i < n; i++ )
{
    dst[i] = Complex.Zero;

    arg = - (int) direction * 2.0 * System.Math.PI * (double) i / (double) n;

    // sum source elements
    for ( int j = 0; j < n; j++ )
    {
        cos = System.Math.Cos( j * arg );
        sin = System.Math.Sin( j * arg );

        dst[i].Re += ( data[j].Re * cos - data[j].Im * sin );
        dst[i].Im += ( data[j].Re * sin + data[j].Im * cos );
    }
}
它使用的是自定义的Complex类(与4.0之前的版本相同)。大多数数学与您已实现的数学相似,但内部迭代会在实数部分和虚数部分上执行其他数学运算。 进一步更新: 经过一些实施和测试,我发现上面的代码和问题中提供的代码产生了相同的结果。根据注释,我还发现此代码生成的内容与WolframAlpha生成的内容之间有什么区别。结果的差异在于,Wolfram似乎对结果应用了1 / sqrt(N)的归一化。在提供的Wolfram链接中,如果每个值都乘以Sqrt(2),则这些值与上述代码生成的值相同(不考虑取整误差)。我通过将3、4和5值传递给Wolfram进行了测试,发现在Sqrt(3),Sqrt(4)和Sqrt(5)方面我的结果有所不同。根据维基百科提供的离散傅立叶变换信息,它确实提到了归一化处理,以使DFT和IDFT的变换统一。这可能是您需要向下看以修改代码或了解Wolfram可能正在做的事情的途径。
您的代码实际上几乎是正确的(您在逆变换中缺少1 / N)。事实是,您使用的公式通常用于计算,因为它更轻便,但是在纯理论环境(以及Wolfram)中,您将使用归一化为1 / sqrt(N)的变换来使变换统一。 即您的公式将是:
Xk = 1/sqrt(N) * sum(x[n] * exp(-i*2*pi/N * k*n))

x[n] = 1/sqrt(N) * sum(Xk * exp(i*2*pi/N * k*n))
这只是归一化的约定,只有幅度会发生变化,因此您的结果也不会那么糟(如果您没有在逆变换中忘记1 / N)。 干杯

要回复问题请先登录注册