为什么傅里叶域中的零填充会导致复变的逆变换?

时间:2017-10-16 12:22:32

标签: matlab signal-processing fft interpolation ifft

如果我从一个只有真值的信号开始,执行fft和ifft会返回准确的信号,没有预期的复杂条目。但是,如果我用零填充fft以获得时域中的插值,则反fft总是变为复数双。我已经注意执行fftshift()然后在两侧打垫,这样对称性就不会被打破。以下是一个示例代码,显示了此行为。我是以错误的方式看待这个问题,还是在零填充过多后计算错误?我该如何克服这个问题?

代码:

%%%%%%%%%

x=linspace(0,2*pi,200);

y = sin(x)+sin(2*x);

Y = fftshift(fft(y));

n=400;

x1 = linspace(0,2*pi,n);

Y1 = zeros(1,n);

Y1((n-200)/2+1:end-(n-200)/2) = Y;

y2 = ifft(fftshift(2*Y1));

plot(x,y);

hold on;

plot(x1,y2(1:end),'x-');

isreal(y)==isreal(y2)

%%

2 个答案:

答案 0 :(得分:2)

可能是一个错误,或者没有忽略微观的舍入误差值。对于IFFT严格实际的结果(微小数值噪声量除外),复数输入向量必须在元素0周围精确共轭对称(或者对于偶数N,在N / 2周围)。

答案 1 :(得分:0)

您的代码有几个小问题:

  1. 原始信号的样本数及其FFT应为奇数。要了解原因,请注意FFT的第一个条目是零频率分量,它没有对称频率。 剩余频率的数量应该是偶数,因此它们可以分成两个对称部分,并且可以在两个部分之间插入额外的零。

  2. 不应使用linspace创建时间轴。由于linspace修复了两个端点,因此您无法获得2的精确比例因子。为此,您需要使用:colon)手动创建轴。

  3. 第二个fftshift应为ifftshift。这在这里并不重要,因为零填充FFT的大小均匀,因此fftshiftifftshift重合。但作为一般规则,您应使用ifftshift撤消fftshift的操作。

  4. 因此,代码变为:

    x = (0:200)/201*2*pi;
    y = sin(x)+sin(2*x);
    Y = fftshift(fft(y));
    x1 = (0:401)/402*2*pi;
    Y1 = [zeros(1,101) Y zeros(1,100)];
    y2 = ifft(ifftshift(2*Y1)); % or fftshift, since length is even
    plot(x,y,'o-');
    hold on;
    plot(x1,y2,'.:');
    isreal(y)==isreal(y2)
    max(abs(y-y2(1:2:end))) % should be of the order of eps
    

    现在我们可以检查一下

    • 这两个信号都是真实的:

      >> isreal(y)==isreal(y2)
      ans =
        logical
         1
      

      更好的测试是检查y1的虚部(由于数值精度问题而可能不是零),其大小为eps

    • y1的每个其他样本都与y中的相应样本一致,最多为eps的数字错误:

      >> max(abs(y-y2(1:2:end)))
      ans =
           6.661338147750939e-16
      

    enter image description here