预期为零的非零 DFT 分量?

信息处理 fft 自由度 阶段 震级
2022-02-13 11:12:17

我在 Octave 中实现 DFT。这是我的代码:

function [real_comp, imag_comp] = mydft (samples)
    N = columns(samples);
    for m = 1:N
        real_accum = 0;
        imag_accum = 0;
        for n = 1:N
            real_factor = cos((2 * pi * (n-1) * (m-1)) / N);
            # imag_factor = -I * sin((2 * pi * (n-1) * (m-1)) / N);
            imag_factor = sin((2 * pi * (n-1) * (m-1)) / N);
            real_accum += real_factor * samples(n);
            imag_accum += imag_factor * samples(n);
        endfor
        real_comp(m) = real_acuum;
        imag_comp(m) = imag_accum;
    endfor
endfunction

我的目标是计算每个 DFT bin 的大小并绘制它。我传入了一个纯实样本列表,并将实部和虚部存储在不同的变量中。这是我正在使用的样本向量:

samples = [0.3535, 0.3535, 0.6464, 1.0607, 0.3535, -1.0607, -1.3535, -0.3535]

样品经过精心挑选,以防止在fs = 8KHz. DFT 幅度的图表正是我所期望的。这没什么不好。但我没有得到的是,我的 8 点 DFT 中的一些分量应该为零,但并不完全为零,而是一个非常小的接近于零的值。fft()另一方面,内置函数已将我期望的组件归零。

例如,我使用以下代码打印由我的 DFT 和 octave 的 FFt 生成的输出向量的元素:

fft_out = fft(samples);
[real, imag] = mydft(samples);
dft_out = real + (-I * imag);
for i=1:columns(samples)
    disp(fft_out(i));
    disp(dft_out(i));
    printf("\n");
endfor

点对点比较如下表所示:

bin_index fft_out dft_out
1 -1.0000e-04 -1.0000e-04
2 0.00000 - 3.99988i 4.7184e-16 - 3.9999e+00i
3 1.4141 + 1.4144i 1.4141 + 1.4144i
4 0.0000e+00 - 8.0820e-05i 1.3878e-16 - 8.0820e-05i
5 -1.0000e-04 -1.0000e-04 - 1.4350e-16i
6 0.0000e+00 + 8.0820e-05i 2.3037e-15 + 8.0820e-05i
7 1.4141 - 1.4144i 1.4141 - 1.4144i
8 0.00000 + 3.99988i -2.0817e-15 + 3.9999e+00i

现在,我不会太在意微小的差异,但如果我计算 和 的相位fft_outdft_out

disp(arg(fft_out))
disp(arg(dft_out))

在某些情况下,我会翻转标志:

fft_out: 3.14159  -1.57080   0.78550  -1.57080   3.14159   1.57080  -0.78550   1.57080
dft_out:-3.14159  -1.57080   0.78550  -1.57080  -3.14159   1.57080  -0.78550   1.57080

那么,我的 DFT 实现有问题吗?它只是一个舍入或精度问题吗?

2个回答

这些只是舍入误差,您只会得到相位值的翻转符号,这不是问题,因为相位值不明确,即添加或减去的倍数不会改变值的复系数。±π2π

我假设您的代码仅用于教育目的,因为它既不高效也不在数字上准确。

由于您没有(也不能,除非您使用严格的符号转换)使用无限精度算术和值,因此您看到的是数字噪声而不是零(等)。并且噪声值的相位可以是随机的。

FFT 比 DFT 做的算术更少,因此添加更多数值噪声的机会更少。