递归FFT java算法返回空值?

递归FFT java算法返回空值?,java,algorithm,recursion,fft,complex-numbers,Java,Algorithm,Recursion,Fft,Complex Numbers,我目前正在尝试用java实现FFT算法,但遇到了一些问题!我已经测试了算法的所有其他部分,它们似乎工作得很好 我遇到的问题是,在基本情况下,它返回一个复数数组,在基本情况下,a[0]被填充。在执行基本情况之后,执行for循环,其中发现y0[0]和y1[0]为null,尽管将它们分配给基本情况,但对此相当困惑。这显示在System.out.println行中 有人能告诉我我的错误吗 //This method implements the recursive FFT algorithm,

我目前正在尝试用java实现FFT算法,但遇到了一些问题!我已经测试了算法的所有其他部分,它们似乎工作得很好

我遇到的问题是,在基本情况下,它返回一个复数数组,在基本情况下,
a[0]
被填充。在执行基本情况之后,执行for循环,其中发现
y0[0]
y1[0]
null,尽管将它们分配给基本情况,但对此相当困惑。这显示在
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;
    }
}
一些想法:

每当我看到像
Math.ceil(N/2)
在这里一样频繁地重复某些内容时,我认为有理由拥有自己的命名变量。(我知道命名变量并不总是那么容易,但我发现它对易读性至关重要。)

请注意,当
N==1
时,计算结果为
新的复数[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);
我相信您可以跳过对这些数组的
新的复杂[…]
分配,因为您从未实际将任何内容存储到它们中

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

我很惊讶它还没有爆炸--
omega[N]
应该会引发
IndexOutOfBounds
异常

跳出的问题:

  • (int)Math.ceil(N/2)
    您仍在进行
    int
    除法,因此
    Math.ceil()
    无效,并且您的拆分数组可能不适用于奇数
    N
  • 如果只填充
    omega[0]
    omega[N-1]
    ,当您尝试访问
    omega[1]
    时,我希望出现
    NullPointerException
    ,这将在
    N>=6
    时发生
  • omega[N]
    ,萨诺尔德也提到了这一点
  • 分配
    A0
    A1
    ,然后将
    splitInput

  • splitInput的代码以及最初如何调用FFT会很有帮助。此外,还不清楚你所说的“基本情况”是什么意思。您的错误可能来自一个
    新复数[…]
    ,它在创建时包含一个
    null
    s数组,而不是复数的真实实例。我使用
    output=FFT(inputComplex,inputComplex.length)行调用FFT基本情况是输入N的大小为1时。我明白你的意思,但是它们是从基本情况向上赋值的,只是一个注释:你不应该使用数组长度作为方法参数,因为它已经包含在数组中了。这就是所谓的数据复制,它不会给您带来任何好处,但如果您在某个地方犯了错误,您可能会处于不一致的状态。在Fortran和C语言中,必须传递数组长度,但在Java中确实没有必要。1)我不确定Java如何接近整数除法,对于
    N==1
    的情况,我只想确定N/2肯定返回1,而不是0 2)我假设N是2的某个幂3)相同4)这有什么错?谢谢你的帮助!我忽略了“2的力量”条件,所以奇怪的问题不是这里的问题。通常,要获得非负整数的
    上限(n/2)
    (n+1)/2
    。2)
    N==8
    ?然后您将访问
    omega[1]
    ,它将是
    null
    。3) 与
    N
    是否为2的幂无关,
    omega=new Complex[N]
    omega[N]
    是不受限制的。4)
    A0=新复合体[N];A0=someFunction()
    创建一个数组供
    A0
    引用,然后让
    A0
    引用其他数组,这样第一个数组就可以被垃圾收集。不是“错”,因为它会产生错误的结果,只是毫无意义。是的,我用新版本更新了我的原始帖子,仍然得到了一个nullpointerexception:(1)不再需要,但谢谢2)不确定你的意思,为什么
    omega[1]
    会被访问?3) 修正了谢谢(改为
    omega[N-1]
    )4)再次修正。非常感谢您迄今为止的帮助!Re 2):in
    y[k]=y0[k].加(ω[k].次(y1[k])
    k
    。如果
    N>5
    k
    可以变成1,那么
    omega[1]
    最好不要为空。感谢您的帮助,非常感谢。我已经更新了我原来的帖子,加入了修改后的版本,它仍然会引发空指针异常,有什么建议吗?
    Complex A0[] = new Complex[((int) Math.ceil(N/2))];
    Complex A1[] = new Complex[((int) Math.ceil(N/2))];
    
    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);
    
    Complex[] omega = new Complex[N];
    /* ... */
            omega[0] = omega[0].times(omega[N]);