Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/api/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 如何计算离散傅里叶变换?_Algorithm_Fft_Complex Numbers_Dft - Fatal编程技术网

Algorithm 如何计算离散傅里叶变换?

Algorithm 如何计算离散傅里叶变换?,algorithm,fft,complex-numbers,dft,Algorithm,Fft,Complex Numbers,Dft,我一直试图找到一些地方来帮助我更好地理解DFT以及如何计算它,但没有用。所以我需要帮助理解DFT和它的复数计算 基本上,我只是想找一些关于如何计算DFT的例子,并解释它是如何计算的,因为最后,我想创建一个算法来计算它。我假设1D DFT/IDFT 所有DFT都使用此公式: c0+c1=(a0+i.b0)+(a1+i.b1)=(a0+a1)+i.(b0+b1) c0*c1=(a0+i.b0)*(a1+i.b1) =a0.a1+i.a0.b1+i.b0.a1+i.i.b0.b1

我一直试图找到一些地方来帮助我更好地理解DFT以及如何计算它,但没有用。所以我需要帮助理解DFT和它的复数计算


基本上,我只是想找一些关于如何计算DFT的例子,并解释它是如何计算的,因为最后,我想创建一个算法来计算它。

我假设1D DFT/IDFT

所有DFT都使用此公式:

c0+c1=(a0+i.b0)+(a1+i.b1)=(a0+a1)+i.(b0+b1)
c0*c1=(a0+i.b0)*(a1+i.b1)
     =a0.a1+i.a0.b1+i.b0.a1+i.i.b0.b1
     =(a0.a1-b0.b1)+i.(a0.b1+b0.a1)
complex = real+i.0

  • X(k)
    是转换的样本值(复数域)
  • x(n)
    是输入数据样本值(实域或复域)
  • N
    是数据集中的样本数/值数
整个过程通常乘以标准化常数
c
。正如您可以看到的,对于单个值,您需要
N
计算,因此对于所有样本,速度较慢的是
O(N^2)

在这里,您还可以找到有关如何使用1D变换计算2D变换的提示,以及如何通过
N点
DFT和IDFT计算
N点
DCT和IDCT的提示

快速算法

有一些快速算法是基于将这个方程分别分解为奇数偶数部分的(它给出了
2xn/2
和),这也是每个值的
O(N)
,但这两部分是相同的方程
+/-
一些常量调整。因此,可以直接从第一个计算出一半。这会导致每个值
O(N/2)
。如果以递归方式应用此函数,则每个值都会得到
O(log(N))
。因此,整个过程变成了
O(N.log(N))
,这非常棒,但也增加了以下限制:

所有DFFT都需要输入数据集的大小等于2的幂

所以它可以被递归地拆分。对于无效的数据集大小(在音频技术中,有时甚至是相移),使用最接近2的更大幂的零填充。看这里:

  • 关于
复数

  • c=a+i*b
  • c
    是复数
  • a
    是它的真实部分(Re)
  • b
    是它的虚部(Im)
  • i*i=-1
    是虚单位
所以计算是这样的

添加:

c0+c1=(a0+i.b0)+(a1+i.b1)=(a0+a1)+i.(b0+b1)
c0*c1=(a0+i.b0)*(a1+i.b1)
     =a0.a1+i.a0.b1+i.b0.a1+i.i.b0.b1
     =(a0.a1-b0.b1)+i.(a0.b1+b0.a1)
complex = real+i.0
乘法:

c0+c1=(a0+i.b0)+(a1+i.b1)=(a0+a1)+i.(b0+b1)
c0*c1=(a0+i.b0)*(a1+i.b1)
     =a0.a1+i.a0.b1+i.b0.a1+i.i.b0.b1
     =(a0.a1-b0.b1)+i.(a0.b1+b0.a1)
complex = real+i.0
极坐标形式

a = r.cos(θ)
b = r.sin(θ)
r = sqrt(a.a + b.b)
θ = atan2(b,a)
a+i.b = r|θ
sqrt

sqrt(r|θ) = (+/-)sqrt(r)|(θ/2)
sqrt(r.(cos(θ)+i.sin(θ))) = (+/-)sqrt(r).(cos(θ/2)+i.sin(θ/2))
实数->复数转换:

c0+c1=(a0+i.b0)+(a1+i.b1)=(a0+a1)+i.(b0+b1)
c0*c1=(a0+i.b0)*(a1+i.b1)
     =a0.a1+i.a0.b1+i.b0.a1+i.i.b0.b1
     =(a0.a1-b0.b1)+i.(a0.b1+b0.a1)
complex = real+i.0
[notes]

  • 不要忘记,您需要将数据转换为不同的阵列(未就位)
  • FFT递归上的标准化常数很棘手(通常类似于
    /=log2(N)
    的东西也取决于递归停止条件)
  • 如果
    N=1或2
    ,不要忘记停止递归
  • 当心FPU会在大数据集上溢出(
    N
    很大)
  • 这里
  • 这里
  • 通常用于计算
    e^(i.x)=cos(x)+i.sin(x)
  • 在这里,您可以找到如何获得奈奎斯特频率
[edit1]我还强烈建议观看这段精彩的视频(我刚找到):

c0+c1=(a0+i.b0)+(a1+i.b1)=(a0+a1)+i.(b0+b1)
c0*c1=(a0+i.b0)*(a1+i.b1)
     =a0.a1+i.a0.b1+i.b0.a1+i.i.b0.b1
     =(a0.a1-b0.b1)+i.(a0.b1+b0.a1)
complex = real+i.0

它描述了几何表示中的(D)FT。我想对其中的一些小东西进行修改,但它仍然非常简单易懂。

看看这里,嗨!当输入大小不是2的幂时,你有什么想法吗?@ChongxuRen将数据集放大,然后将PAD设为零,我认为这是不对的。添加新数据将更改$W_N$。在这个问题上需要更先进的技术@崇旭人我使用FFT和NTT主要用于任意和大型算法,使用简单的零填充的最终结果(在时域)是正确的。对于不同的目的,需要频域中的精确值,您是对的。