Tim*_*sen 12 c# fft complex-numbers c#-4.0
我正在尝试实现离散傅立叶变换,但它不起作用.我可能在某个地方写过一个bug,但我还没有找到它.
基于以下公式:

该函数执行第一个循环,循环遍历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;
}
Run Code Online (Sandbox Code Playgroud)
而实际计算,这可能是错误的地方.
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;
}
Run Code Online (Sandbox Code Playgroud)
接下来解释剩下的代码:
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);
Run Code Online (Sandbox Code Playgroud)
什么时候应该更像是:
transformed += data[i]*Math.Pow(Math.E, Complex.FromPolarCoordinates(1, argument*i));
Run Code Online (Sandbox Code Playgroud)
除非你把这个包裹在方法中 FromPolarCoordinates()
更新:我在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 );
}
}
Run Code Online (Sandbox Code Playgroud)
它使用自定义Complex类(因为它是4.0之前的版本).大部分数学运算与您实现的类似,但内部迭代正在对Real和Imaginary部分进行额外的数学运算.
进一步更新:经过一些实施和测试后,我发现上面的代码和问题中提供的代码产生了相同的结果.我还根据评论发现,这段代码生成的内容与WolframAlpha生成的内容之间存在差异.结果的不同之处在于看起来Wolfram正在对结果应用1/sqrt(N)的归一化.在Wolfram Link中,如果每个值乘以Sqrt(2),那么这些值与上面代码生成的值相同(除了舍入误差).我通过将3个,4个和5个值传递给Wolfram来测试这一点,并且发现我的结果因Sqrt(3),Sqrt(4)和Sqrt(5)而有所不同.基于维基百科提供的离散傅立叶变换信息,它确实提到了归一化以使DFT和IDFT的变换成为单一的.这可能是您需要向下看以修改代码或了解Wolfram可能正在做什么的途径.
| 归档时间: |
|
| 查看次数: |
1646 次 |
| 最近记录: |