傅里叶变换舍入误差

Tim*_*sen 1 c# floating-point double fft

我正在搞乱傅立叶变换.现在我已经创建了一个实现DFT实现的类(没有像FFT atm这样做).这是我用过的实现:

public static Complex[] Dft(double[] data)
    {
        int length = data.Length;
        Complex[] result = new Complex[length];

        for (int k = 1; k <= length; k++)
        {
            Complex c = Complex.Zero;
            for (int n = 1; n <= length; n++)
            {
                c += Complex.FromPolarCoordinates(data[n-1], (-2 * Math.PI * n * k) / length);
            }
            result[k-1] =  1 / Math.Sqrt(length) * c;
        }
        return result;
    }
Run Code Online (Sandbox Code Playgroud)

这些是我得到的结果 Dft({2,3,4})

替代文字

好吧,看起来还不错,因为那些是我期望的值.我发现只有一件事令人困惑.这一切都与双打的四舍五入有关.

首先,为什么前两个数字不完全相同(0,8660..443 8)vs(0,8660..443).为什么它不能计算零,你期望它.我知道2.8E-15非常接近于零,但事实并非如此.

任何人都知道这些,边缘的错误是如何发生的,如果我能够并且想要对它做些什么.

似乎没有真正的问题,因为它只是小错误.但是,如果您要比较2个值,那么如何处理这些舍入误差.

5,2 + 0i != 5,1961524 + i2.828107*10^-15
Run Code Online (Sandbox Code Playgroud)

干杯

Car*_*rum 6

我想你已经向自己解释过 - 精确度有限意味着精度有限.故事结局.

如果你想清理结果,你可以将自己的四舍五入到更合理数量的重要数字 - 然后你的零将显示在你想要的位置.

要回答您的评论提出的问题,请不要尝试直接比较浮点数 - 使用范围:

if (Math.Abs(float1 - float2) < 0.001) {
  // they're the same!
}
Run Code Online (Sandbox Code Playgroud)

comp.lang.c常见问题有很多有关浮点问题和答案,你可能有兴趣阅读.

  • 请注意,这种事情可能导致其自身的问题.例如,假设有三个,float1,float2和float3.您可以轻松地进入一种情况,即代码报告float1与float2"相同",而float2与float3"相同",但float1与float3不同.这是一个奇怪的情况; 诸如排序算法之类的许多算法都假设等于相同的事物彼此相等; 当你提出不是等价关系的"平等"实现时要非常小心. (3认同)