直接回答您的问题:您拥有正确的数据结构(即list)。但是,您也有一些严重的 Python/算法问题。 让我们从高级问题开始,然后从那里开始......
首先,你所拥有的是一个幼稚的 DFT,而不是 FFT。这个问题被标记为 FFT,尽管您没有在问题本身的任何地方引用 FFT,所以也许您已经知道这一点,但我想我会为可能不知道的其他人提及它。 FFT 在O(N log N) 中运行。您在O(N^2) 中运行的内容。巨大差距。它们都输出相同的东西,因为它们都是傅立叶变换(尽管比例因子可以使它们在实现方面有所不同),但一个速度很快(因此 FFT)。使用简单的 DFT 通常不会给您带来太多好处:我们使用 FFT 是因为它们的计算效率很高。如果不是,我们将在时域中做所有事情并完成它!
其次,您的缩进/算法不正确。您需要:
re = 0
im = 0
就在每个内部循环之前。
另外,你需要有这个部分(我已经修改了它的正确性):
# re = re/N This is not a part of the definition, remove it
# im = im/N Also not a part of the definition, remove it
h = (re, im)
X.insert(k, h)
在第一个循环内。
第三,Python 有一个内置类型来表示复数。所以你想要:
# There are other (more idiomatic?) ways to create a complex number,
# but this probably looks natural to a Java dev
h = complex(re, im)
因此,我为使 DFT 正确(根据维基百科的定义)所做的修改如下所示:
import math
pi = math.pi
def dft(x):
X=[]
N = len(x)
for k in range(0,N):
re = 0
im = 0
for n in range(0,N):
phi = (2*pi*k*n)/N
re += (x[n]*math.cos(phi))
im -= (x[n]*math.sin(phi))
h = (re, im)
X.insert(k, complex(re, im))
return (X)
最后,Python 有一些非常强大的内置插件和 3rd 方库,利用它们是明智之举。虽然numpy技术上不是内置的-in,它被广泛使用,它也可能是(我认为它实际上是在 MacOS 上随 CPython 一起提供的)。 numpy 将比您将要拼凑的任何东西更快、更正确,并且具有更好的功能/支持/工具。 FFT 长期以来一直是一个已解决的问题:重新发明轮子是没有意义的!你可以在你的 shell 中通过一个简单的pip install numpy 在你的生态系统中获得numpy(是的,这很容易,没有 Maven,没有 Gradle,没有 ANT,没有废话!)
经过上述修复后,我们得到:
import numpy as np
def pretty_print_result(x):
for item in x:
print(item)
numpy_result = np.fft.fft([1,2,3,4,5,6]) # <-- This is the most "Pythonic" thing to do imo!
our_result = dft([1,2,3,4,5,6])
print('Numpys: ')
pretty_print_result(numpy_result)
print()
print('Ours: ')
pretty_print_result(our_result)
输出:
Numpys:
(21+0j)
(-3+5.19615242271j)
(-3+1.73205080757j)
(-3+3.10862446895e-15j)
(-3-1.73205080757j)
(-3-5.19615242271j)
Ours:
(21+0j)
(-3.000000000000001+5.196152422706631j)
(-2.999999999999996+1.7320508075688759j)
(-3-1.286250527486674e-14j)
(-3.0000000000000084-1.7320508075688812j)
(-3.000000000000009-5.196152422706645j)
这是相同的结果,减去一些浮点恶作剧。同样,numpy 几乎肯定会比你拼凑起来的任何东西都更准确和更快,我不能推荐它用于科学计算。
快速速度比较(在 IPython 中加载这个,并将修改后的 dft 函数存储在一个名为 test.py 的文件中):
In [1]: from test import dft
In [2]: import numpy as np
In [3]: %timeit np.fft.fft([1,2,3,4,5])
The slowest run took 9.24 times longer than the fastest. This could mean that an intermediate result is being cached.
100000 loops, best of 3: 12.5 µs per loop
In [4]: %timeit dft([1,2,3,4,5])
10000 loops, best of 3: 21.7 µs per loop
嗯,看起来还不错。它的速度大约是原来的两倍。但请记住,numpy在算法上更快(嗯......它也在运行本机代码),这意味着随着输入的增长,加速因子本身也会随着输入的增长而增加:
In [5]: %timeit np.fft.fft(range(1000))
10000 loops, best of 3: 130 µs per loop
In [6]: %timeit dft(range(1000))
1 loop, best of 3: 922 ms per loop
现在numpy 的速度提高了 1000 倍以上,而且随着输入大小的增加,它只会比原始版本更快。
HTH!祝你在 Python 道路上好运!