11

我很难理解什么应该是一个简单的概念。我在 MATLAB 中构造了一个实数对称向量。当我在 MATLAB 中进行 FFT 时,结果具有重要的虚部,尽管傅里叶变换的对称规则表明实对称函数的 FT 也应该是实数和对称的。我的示例代码:

N = 1 + 2^8;
k = linspace(-1,1,N);

V = exp(-abs(k));

Vf1 = fft(fftshift(V));
Vf2 = fft(ifftshift(V));
Vf3 = ifft(fftshift(V));
Vf4 = ifft(ifftshift(V));
Vf5 = fft(V);
Vf6 = ifft(V);

disp([isreal(Vf1) isreal(Vf2) isreal(Vf3) isreal(Vf4) isreal(Vf5) isreal(Vf6)])

结果:

0 0 0 0 0 0

没有组合(i)fft(i)fftshift导致实对称向量。我已经尝试过偶数和奇数 N (N = 2^8vs. N = 1+2^8)。

我确实尝试查看k+flip(k)并且有一些残差在 的数量级上eps(1),但是这些残差也是对称的,并且 FFT 的虚部不是在 的数量级上以模糊的形式出现eps(1),而是具有与实部相当的幅度。

我错过了什么明显的东西?

我错过了令人眼花缭乱的事情:

FFT 不是对所有空间的积分,因此它假设一个周期信号。上面,当我选择偶数时,我复制了周期中的最后一个点N,因此没有办法将它移动以在没有分数索引的情况下将零频率放在开头,而分数索引不存在。

关于我的选择k。这不是任意的。我试图解决的实际问题是生成一个模型 FTIR 干涉图,然后我将用 FFT 得到一个光谱。k是干涉仪行进的距离,它被转换为波数中的频率。在实际问题中会有各种比例因子,因此生成函数 V 将产生物理上有意义的数字。

4

4 回答 4

9

它是

Vf = fftshift(fft(ifftshift(V)));

也就是说,您需要ifftshift在时域中将样本解释为对称函数的样本,然后fftshift在频域中再次使对称性变得明显。

这仅适用于N奇数。甚至,对称函数的概念没有意义:没有办法移动信号以使其相对于N原点对称(原点需要“在两个样本之间”,这是不可能的)。

对于您的示例V,上面的代码给出了Vf实数和对称的。下图是用 生成的semilogy(Vf),因此可以看到小值和大值。(当然,您可以修改水平轴,使图表以 0 频率为中心;但无论如何,图表看起来是对称的。)

在此处输入图像描述

于 2014-07-30T16:56:15.787 回答
7

@Yvon is absolutely right with his comment about symmetry. Your input signal looks symmetrical, but it isn't because symmetry is related to origin 0. Using linspace in Matlab for constructing signals is mostly a bad choice. Trying to repair the results with fftshift is a bad idea too.

Use instead:

k = 2*(0:N-1)/N - 1;

and you will get the result you expect. However the imaginary part of the transformed values will not be perfectly zero. There is some numerical noise.

>> max(abs(imag(Vf5)))
ans =
2.5535e-15

Answer to Yvon's question:

Why? >> N = 1+2^4 N = 17 >> x=linspace(-1,1,N) x = -1.0000 -0.8750 -0.7500 -0.6250 -0.5000 -0.3750 -0.2500 -0.1250 0 0.1250 0.2500 0.3750 0.5000 0.6250 0.7500 0.8750 1.0000 >> y=2*(0:N-1)/N-1 y = -1.0000 -0.8824 -0.7647 -0.6471 -0.5294 -0.4118 -0.2941 -0.1765 -0.0588 0.0588 0.1765 0.2941 0.4118 0.5294 0.6471 0.7647 0.8824 – Yvon 1

Your example is not a symmetric (even) function, but an antisymmetric (odd) function. However, this makes no difference.

For a antisymmetric function of length N the following statement is true:

f[i] == -f[-i] == -f[N-i]

The index i runs from 0 to N-1.

Let us see was happens with i=2. Remember, count starts with 0 and ends with 16.

x[2] = -0.75
-x[N-2] == -x[17-2] == -x[15] = (-1) 0.875 = -0.875
x[2] != -x[N-2]

y[2] = -0.7647
-y[N-2] == -y[15] = (-1) 0.7647
y[2] == y[N-2]

The problem is, that the origin of Matlab vectors start at 1. Modulo (periodic) vectors start with origin 0. This difference leads to many misunderstandings.

Another way of explanation why linspace(-1,+1,N) is not correct:

Imagine you have a vector which holds a single period of a periodic function, for instance a Cosinus function. This single period is one of a infinite number of periods. The first value of your Cosinus vector must not be same as the last value of your vector. However,that is exactly what linspace(-1,+1,N) does. Doing so, results in a sequence where the last value of period 1 is the same value as the first sample of the following period 2. That is not what you want. To avoid this mistake use t = 2*(0:N-1)/N - 1. The distance t[i+1]-t[i] is 2/N and the last value has to be t[N-1] = 1 - 2/N and not 1.

Answer to Yvon's second comment

Whatever you put in an input vector of a DFT/FFT, by theory it is interpreted as a periodic function. But that is not the point.

DFT performs an integration.

fft(m) = Sum_(k=0)^(N-1) (x(k) exp(-i 2 pi m k/N )

The first value x(k=0) describes the amplitude of the first integration interval of length 1/N. The second value x(k=1) describes the amplitude of the second integration interval of length 1/N. And so on.

The very last integration interval of the symmetric function ends with same value as the first sample. This means, the starting point of the last integration interval is k=N-1 = 1-1/N. Your input vector holds the starting points of the integration intervals.

Therefore, the last point of symmetry k=N is a point of the function, but it is not a starting point of an integration interval and so it is not a member of the input vector.

于 2014-07-31T10:14:05.327 回答
2

实施“对称”概念时遇到问题。纯实偶数(或“对称”)函数具有一个也是实数偶数的傅里叶变换函数。“偶数”是关于 y 轴或 t=0 线的对称性。

然而,在 Matlab 中实现信号时,总是从 t=0 开始。也就是说,没有办法“定义”从时间原点之前开始的信号。

在互联网上搜索了一段时间后,我发现了这一点 - 在 fft 和 ifft 的输入中正确使用 fftshift 和 ifftshift

正如 Luis 所指出的,您需要ifftshift在将信号输入之前执行fft。原因从未在 Matlab 中记录,但仅在该线程中记录。由于历史原因, 和 的输出和输入被交换。也就是说,时域或频域中的信号不是从to排序(自然顺序),而是从to再到to排序。这意味着,正确的编码方式是,但大多数人在大多数情况下都忽略了这一点fftifft-N/2N/2-10N/2-1 -N/2-1fft( ifftshift(V) ). 为什么它被默默地忽略而不是引发巨大的问题是因为大多数问题都放在信号的幅度上,而不是相位上。由于循环移位不会影响幅度谱,因此这不是问题(即使对于编写文档的 Matlab 人员也是如此)。

检查幅度相等 -

Vf2 = fft(ifftshift(V));
Vf5 = fft(V);
Va2 = abs(fftshift(Vf2));
Va5 = abs(fftshift(Vf5));

>> min(abs(Va2-Va5)<1e-10)

ans =

     1

看看相位错误有多严重——

Vp2 = angle(fftshift(Vf2));
Vp5 = angle(fftshift(Vf5));

无论如何,正如我在评论中所写,在将您的代码复制并粘贴到一个新鲜干净的 Matlab 之后,它会给出0 1 0 1 0 0.

对于您关于 N=even 和 N=odd 的问题,我的观点是当 N=even 时,信号不对称,因为时间原点两侧的点数不相等。

于 2014-07-30T17:17:43.640 回答
2

只需在“k = linspace(-1,1,N);”之后添加以下行

k(end)=[];

它将删除数组的最后一个元素。这被定义为对称数组。

还要考虑 isreal(complex(1,0)) 是假的!!!isreal 函数只检查内存存储格式。所以 1+0i 在上面的例子中不是真实的。

你已经定义了你的函数来检查实数(像这样)

myisreal=@(x) all((abs(imag(x))<1e-6*abs(real(x)))|(abs(x)<1e-8));

最后你的源代码应该是这样的:

N = 1 + 2^8;
k = linspace(-1,1,N);

k(end)=[];

V = exp(-abs(k));


Vf1 = fft(fftshift(V));

Vf2 = fft(ifftshift(V));
Vf3 = ifft(fftshift(V));
Vf4 = ifft(ifftshift(V));
Vf5 = fft(V);
Vf6 = ifft(V);

myisreal=@(x) all((abs(imag(x))<1e-6*abs(real(x)))|(abs(x)<1e-8));

disp([myisreal(Vf1) myisreal(Vf2) myisreal(Vf3) myisreal(Vf4) myisreal(Vf5) myisreal(Vf6)]);
于 2015-09-26T03:59:10.700 回答