FFT 算法在我的输出数字上给出了错误的符号

信息处理 fft 算法 数学 C#
2022-02-21 12:01:30

另一个堆栈交换(stackoverflow 和计算机科学堆栈交换)告诉我在这里发帖 - 所以希望现在我可以从了解算法的人那里得到一些帮助,但如果这不是这里的主题,那么我有点用完了地方问....

我编写了自己的 FFT 算法来学习它 - 但我得到的结果与我的预期不同(正确的数字但错误的符号),但我不知道为什么。

我希望这里有一个对 FFT 算法有很好理解的人可以理解我做错了什么,我目前怀疑这是我的旋转因素 - 但我现在不确定......

首先,我预先计算所有的旋转因子和指数。旋转计算如下:

        for (int stage = 0; stage < _passes; stage++) //log(N)/log(2)
        {
            for (int i = 0; i < _N; i++) //N = 2^n
            {
                //wing span, 2^1, 2^2 etc
                float span = pow(2, stage+1); 
                float k = (i * _N / span) % _N;
                float a = pi2 * k / _N;

                //iFFT uses complex positive coefficients: exp(i*2*pi*k/N)
                Vector2 twiddle = new Vector2(cos(a), sin(a));

                //FFT uses complex conjugate: exp(-i*2*pi*k/N)
                Vector2 twiddleConj = twiddle.ComplexConjugate();

                int arrIndex = stage * _N + i;
                _twiddlesR[arrIndex] = twiddle; //inverse array
                _twiddlesF[arrIndex] = twiddleConj; //forward array
            }
        }

这是输出N=4

  First stage:
  [0] + (1+0i)[2]
  [2] +(-1+0i)[0]
  [1] + (1+0i)[3]
  [3] +(-1+0i)[1]
  Second stage:
  [0] + (1+0i)[2]
  [1] +  (0-i)[3]
  [2] +(-1+0i)[0]
  [3] +  (0+i)[1]

我使用以下代码运行 FFT:

for (int stage = 0; stage < _passes; stage++)
{
    for (int k = 0; k < _N; k++)
    {
        PerformFft(stage, k);
    }
}

我的 FFT 函数:

    private void PerformFft(int stage, int k)
    {
        int arrIndex = stage * _N + k;
        Vector2[] twiddleArr = _isForward ? _twiddlesF : _twiddlesR;
        Vector2Int twiddleIndex = _twiddleIndices[arrIndex];
        Vector2 twiddle = twiddleArr[arrIndex];

        //ping pong between two read/write arrays by checking if stage is even or odd
        Vector2[] writeArr = stage % 2 == 0 ? _complexArr2 :_complexArr1;
        Vector2[] readArr = stage % 2 == 0 ? _complexArr1 :_complexArr2;

        
        Vector2 complexA = readArr[twiddleIndex.x]; 
        Vector2 complexB = readArr[twiddleIndex.y]; 

        Vector2 result = complexA + complexB.ComplexMultiply(twiddle);
        writeArr[k] = result;
        
    }

对于输出,我得到了正确的数字,但我得到了错误的符号,这里有一些数据:

Input:
0 + 0i
1 + 0i
2 + 0i
3 + 0i
Forward FFT Output:
6 + 0i
2 - 2i
2 + 0i
2 + 2i

但根据这个 FFT 计算器,我接近正确答案,但符号错误:https ://scistatcalc.blogspot.com/2013/12/fft-calculator.html

谁能看到我在这里犯了什么逻辑错误?到目前为止,已经坚持了一周。

1个回答

颠倒输入序列的顺序将提供与 OP 实现的结果相同的结果,但并不是说这正是它发生在这里的原因。下面展示了每个阶段后DIT算法的细节;逐步将每个元素与代码进行比较应该会发现实际错误。

DIT 算法

解释 OP 的结果(我假设 [x] 代表索引)揭示了核心 2 pt DFT 蝶形运算中的错误。

而 2 pt DFT 给出为

Y[0]=X[0]+X[1]
Y[1]=X[0]X[1]

虽然 OP 正在执行以下操作:

Y[0]=X[0]+X[1]
Y[1]=X[1]X[0]

作为2-Pt DFT 输入,作为 2-Pt DFT 输出。X[0]X[1]Y[0]Y[1]

  First stage:
  [0] + (1+0i)[2]   = 0+2
  [2] +(-1+0i)[0]   = 2-0   (should be 0-2= -2!)
  [1] + (1+0i)[3]   = 1+3
  [3] +(-1+0i)[1]   = 3-1  (should be 1 -3= -2!)
  Second stage:
  [0] + (1+0i)[2]       
  [1] +  (0-i)[3]
  [2] +(-1+0i)[0]
  [3] +  (0+i)[1]