递归FFT java算法返回空值?
我目前正在尝试用java实现FFT算法,但遇到了一些问题!我已经测试了算法的所有其他部分,它们似乎工作得很好 我遇到的问题是,在基本情况下,它返回一个复数数组,在基本情况下,递归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,
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):iny[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]);