JTransforms FFT:偶数和奇数情况之间的差异

时间:2017-03-01 10:33:45

标签: java algorithm fft

我对任意长度的数组执行FFT。 API可引用如下:

  

realForward

http://localhost/tutor_crm/#/main/home/edit/4
     

计算实数数据的1D前向DFT,将结果保留在public void realForward(double[] a) 中。   输出数据的物理布局如下:

     

如果a是偶数

n
     

如果a[2*k] = Re[k], 0<=k<n/2 a[2*k+1] = Im[k], 0<k<n/2 a[1] = Re[n/2] 是奇数,那么

n

在阅读了几个已经回答的问题之后,我仍然无法定义循环以获得幅度值a[2*k] = Re[k], 0<=k<(n+1)/2 a[2*k+1] = Im[k], 0<k<(n-1)/2 a[1] = Im[(n-1)/2]

每种情况下m_k=sqrt(RE_k²+IM_k²)的内容是什么? (或者作者实际上是指index=1)?

1 个答案:

答案 0 :(得分:3)

a数组中的大多数返回值都很复杂,并以其固有的频域顺序返回。然而,有一些特殊情况:

  • 0Hz频率分量,纯粹是真实的(对于偶数和奇数n
  • 奈奎斯特频率分量,对奇数n来说也是纯粹的。

然后,作者选择将所有正常案例放在索引2之后,并在a[0]a[1]中保留一对值以处理这些特殊情况。 a[0]中的内容是0Hz频率分量。对于a[1],它变得有点棘手。它始终是最高频率成分的一部分,但如果n是偶数或奇数,如何处理它会有所不同。对于偶数n,则最后一个频率分量纯粹是真实的,因此可以直接存储在a[1]中。对于奇数n,最后一个频率分量不是纯粹的真实,所以我们仍然需要一对数组元素来存储结果。在这种情况下,由于对在索引2处开始,并且数组具有最后一对不适合的奇数大小,因此作者使用a[1]来表示缺少的元素。

或许最简单的方法是通过几个例子。所以,这是一个偶数n=8示例:

Bin  Complex result Comments
===  ============== =============
0    (a[0],0)       Purely real
1    (a[2],a[3])
2    (a[4],a[5])
3    (a[6],a[7])
4    (a[1],0)       Purely real
5    (a[6],-a[7])   Symmetric with bin 3
6    (a[4],-a[5])   Symmetric with bin 2
7    (a[2],-a[3])   Symmetric with bin 1

这是一个奇怪的n=7例子:

Bin  Complex result Comments
===  ============== =============
0    (a[0],0)       Purely real
1    (a[2],a[3])
2    (a[4],a[5])
3    (a[6],a[1])
4    (a[6],-a[1])   Symmetric with bin 3
5    (a[4],-a[5])   Symmetric with bin 2
6    (a[2],-a[3])   Symmetric with bin 1

最后计算大小的相应代码:

double[] m = new double[n/2 + 1];

boolean isOdd = ((n % 2) == 1);
if (isOdd) {
  // odd case
  m[0] = abs(a[0]);
  for (int i = 1; i < (n-1)/2; i++) {
    m[i] = sqrt(a[2*i]*a[2*i] + a[2*i+1]*a[2*i+1]);
  }
  m[(n-1)/2] = sqrt(a[n-1]*a[n-1] + a[1]*a[1]);
} else {
  // even case
  m[0] = abs(a[0]);
  for (int i = 1; i < n/2; i++) {
    m[i] = sqrt(a[2*i]*a[2*i] + a[2*i+1]*a[2*i+1]);
  }
  m[n/2] = abs(a[1]);
}