如果我从一个只有真值的信号开始,执行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)
%%
答案 0 :(得分:2)
可能是一个错误,或者没有忽略微观的舍入误差值。对于IFFT严格实际的结果(微小数值噪声量除外),复数输入向量必须在元素0周围精确共轭对称(或者对于偶数N,在N / 2周围)。
答案 1 :(得分:0)
您的代码有几个小问题:
原始信号的样本数及其FFT应为奇数。要了解原因,请注意FFT的第一个条目是零频率分量,它没有对称频率。 剩余频率的数量应该是偶数,因此它们可以分成两个对称部分,并且可以在两个部分之间插入额外的零。
不应使用linspace
创建时间轴。由于linspace
修复了两个端点,因此您无法获得2
的精确比例因子。为此,您需要使用:
(colon
)手动创建轴。
第二个fftshift
应为ifftshift
。这在这里并不重要,因为零填充FFT的大小均匀,因此fftshift
和ifftshift
重合。但作为一般规则,您应使用ifftshift
撤消fftshift
的操作。
因此,代码变为:
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