【发布时间】:2011-08-17 15:40:27
【问题描述】:
我想将 Matlab 的快速傅里叶变换函数 fft() 移植到本机 Java 代码中。
作为起点,我使用JMathLib 的代码,其中 FFT 的实现方式如下:
// given double[] x as the input signal
n = x.length; // assume n is a power of 2
nu = (int)(Math.log(n)/Math.log(2));
int n2 = n/2;
int nu1 = nu - 1;
double[] xre = new double[n];
double[] xim = new double[n];
double[] mag = new double[n2];
double tr, ti, p, arg, c, s;
for (int i = 0; i < n; i++) {
xre[i] = x[i];
xim[i] = 0.0;
}
int k = 0;
for (int l = 1; l <= nu; l++) {
while (k < n) {
for (int i = 1; i <= n2; i++) {
p = bitrev (k >> nu1);
arg = 2 * (double) Math.PI * p / n;
c = (double) Math.cos (arg);
s = (double) Math.sin (arg);
tr = xre[k+n2]*c + xim[k+n2]*s;
ti = xim[k+n2]*c - xre[k+n2]*s;
xre[k+n2] = xre[k] - tr;
xim[k+n2] = xim[k] - ti;
xre[k] += tr;
xim[k] += ti;
k++;
}
k += n2;
}
k = 0;
nu1--;
n2 = n2/2;
}
k = 0;
int r;
while (k < n) {
r = bitrev (k);
if (r > k) {
tr = xre[k];
ti = xim[k];
xre[k] = xre[r];
xim[k] = xim[r];
xre[r] = tr;
xim[r] = ti;
}
k++;
}
// The result
// -> real part stored in xre
// -> imaginary part stored in xim
不幸的是,当我对它进行单元测试时,它并没有给我正确的结果,例如使用数组
双[] x = { 1.0d, 5.0d, 9.0d, 13.0d };
Matlab 中的结果:
28.0
-8.0 - 8.0i
-8.0
-8.0 + 8.0i
我的实现结果:
28.0
-8.0 + 8.0i
-8.0
-8.0 - 8.0i
注意复杂部分的符号是如何错误的。
当我使用更长、更复杂的信号时,实现之间的差异也会影响数字。因此,实现差异不仅与某些符号“错误”有关。
我的问题:如何调整我的实现以使其与 Matlab 实现“相等”? 或者:是否已经有一个库可以做到这一点?
【问题讨论】:
-
如果我在 Matlab 中运行它,我会得到第二组数字。
-
native Java不是矛盾吗? :-) -
您能举例说明尺寸 8 的差异吗?尺寸 16?谢谢。
-
投票结束:您一定犯了一个错误,因为 Matlab(或手动计算)会导致您列出的 第二个 组数字,而不是第一个.
-
@Oli Charlesworth Aha:当作为 4x1 矩阵放入 Matlab 时,它实际上会产生相同的数字,而当作为 1x4 矩阵时,它会给出我的问题中给出的错误数字。如何调整实现以使用 double[][] 数组,以便我可以支持真正的矩阵化(具有多行和多列)?