3

我目前正在尝试在java中实现FFT算法并且遇到了一些麻烦!我已经很好地测试了算法的所有其他部分,它们似乎工作正常。

我遇到的麻烦是,在基本情况下,它返回一个复数数组,在基本情况下A[0]已填充。在执行基本案例之后,尽管将它们分配给基本案例,但在发现为null的地方执行了 for 循环y0[0],对此非常困惑。这显示在该行中y1[0]System.out.println

谁能告诉我我的方式的错误?

    //This method implements the recursive FFT algorithm, it assumes the input length
//N is some power of two
private static Complex[] FFT(Complex[] A, int N) { 
    double real, imag;
    Complex A0[] = new Complex[((int) Math.ceil(N/2))]; 
    Complex A1[] = new Complex[((int) Math.ceil(N/2))];
    Complex[] omega = new Complex[N];
    Complex[] y = new Complex[N];
    Complex[] y0 = new Complex[((int) Math.ceil(N/2))];
    Complex[] y1 = new Complex[((int) Math.ceil(N/2))]; 

    //base case
    if (N == 1) {
        return A;
    }
    else {
        real = Math.cos((2*Math.PI)/N); if (real < 1E-10 && real > 0) real = 0;
        imag = Math.sin((2*Math.PI)/N); if (imag < 1E-10 && imag > 0) imag = 0;
        omega[N-1] = new Complex(real, imag);
        omega[0] = new Complex(1, 0);
        A0 = splitInput(A, 1);
        A1 = splitInput(A, 0);
        //recursive calls
        y0 = FFT(A0, N/2);
        y1 = FFT(A1, N/2);
        for (int k = 0; k < ((N/2)-1); k++) {
            System.out.print("k: " + k + ", y0: " + y0[k]); System.out.println(", y1: " + y1[k]);
            y[k] = y0[k].plus(omega[k].times(y1[k]));
            y[k+(N/2)] = y0[k].minus(omega[k].times(y1[k]));
            omega[0] = omega[0].times(omega[N]);
        }
        return y;
    }
}

这是我请求的 splitInput 方法的代码

//This method takes a double array as an argument and returns every even or odd
//element according to the second int argument being 1 or 0
private static Complex[] splitInput(Complex[] input, int even) {
    Complex[] newArray = new Complex[(input.length/2)];

    //Return all even elements of double array, including 0
    if (even == 1) {
        for (int i = 0; i < (input.length/2); i++) {
            newArray[i] = new Complex(input[i*2].re, 0.0);
        }
        return newArray;
    }
    //Return all odd elements of double array
    else {
        for (int i = 0; i < (input.length/2); i++) {
            newArray[i] = new Complex (input[(i*2) + 1].re, 0.0);
        }
    return newArray;
    }
}

编辑:我已经根据你的建议更新了我的代码,仍然从行中得到一个空指针异常,y[k] = y0[k].plus(omega[k].times(y1[k]));因为y0&y1仍然null在基本情况之后 :( 任何进一步的想法?这是更新的算法

//This method implements the recursive FFT algorithm, it assumes the input length
//N is some power of two
private static Complex[] FFT(Complex[] A, int N) { 
    double real, imag;
    Complex[] omega = new Complex[N];
    Complex[] y = new Complex[N];
    Complex[] A0;
    Complex[] A1;
    Complex[] y0;
    Complex[] y1;

    //base case
    if (N == 1) {
        return A;
    }
    else {
        real = Math.cos((2*Math.PI)/N); if (real < 1E-10 && real > 0) real = 0;
        imag = Math.sin((2*Math.PI)/N); if (imag < 1E-10 && imag > 0) imag = 0;;
        omega[N-1] = new Complex(real, imag);
        omega[0] = new Complex(1, 0);
        A0 = splitInput(A, 1);
        A1 = splitInput(A, 0);
        //recursive calls
        y0 = FFT(A0, N/2);
        y1 = FFT(A1, N/2);
        for (int k = 0; k < ((N/2)-1); k++) {
            y[k] = y0[k].plus(omega[k].times(y1[k]));
            y[k+(N/2)] = y0[k].minus(omega[k].times(y1[k]));
            omega[0] = omega[0].times(omega[N-1]);
        }
        return y;
    }
}
4

2 回答 2

2

一些想法:

每当我看到像Math.ceil(N/2)这里一样经常重复的东西时,我认为它证明有自己的命名变量是合理的。(我知道命名变量并不总是那么容易,但我发现它对于易读性至关重要。)

Complex A0[] = new Complex[((int) Math.ceil(N/2))];
Complex A1[] = new Complex[((int) Math.ceil(N/2))];

请注意,当 时N==1,计算结果为new Complex[0]。我不确定这是做什么的,但我认为我会将N == 1基本情况检查放在内存分配之前。

Complex[] y0 = new Complex[((int) Math.ceil(N/2))];
Complex[] y1 = new Complex[((int) Math.ceil(N/2))];
/* ... */
    y0 = FFT(A0, N/2);
    y1 = FFT(A1, N/2);

我相信您可以跳过new Complex[...]这些数组的分配,因为您实际上从未将任何内容存储到其中。

Complex[] omega = new Complex[N];
/* ... */
        omega[0] = omega[0].times(omega[N]);

我很惊讶这还没有爆炸——omega[N]应该引发一个IndexOutOfBounds例外。

于 2011-12-24T00:45:46.983 回答
1

跳出来的问题:

  1. (int) Math.ceil(N/2)您仍在进行int除法,因此Math.ceil()无效,并且您的拆分数组对于奇数可能不正确n
  2. 你只会填充omega[0]omega[N-1]我希望NullPointerException当你尝试访问omega[1]时会发生这种情况N >= 6
  3. omega[N],正如 sarnold 也提到的
  4. 您分配A0A1,然后将结果分配给他们splitInput
于 2011-12-24T00:46:44.300 回答