FFT gives wrong answer for a generating function
7 次查看(过去 30 天)
显示 更早的评论
I am trying to use the generating function below to make a symmetric Toeplitz matrix (a matrix where each diagonal has a constant value). Each
is an element in a size n vector which forms the first row of my matrix A.
where:
from 
from I believe that the
terms are the Fourier Coefficients of
and that I should be able to use a Fourier transform to calculate them. Specifically, I want to use a Fast Fourier Transform with fft().
The problem is that when I use fft(), I get coefficients that are both very large (~10^3) and complex. Since
is real and even in the given interval, the Fourier coefficients should only be real.
Here is my code for how I am trying to use the FFT:
n = 50;
f = linspace(-pi, pi, n); % Establish domain
f = f.^4 + 1; % Calculate f(theta)
f = fft(f); % FFT
The output of f at the end is:
f =
1.0e+03 *
1.1047 + 0.0000i
0.8360 + 0.0526i
0.4487 + 0.0567i
etc...
When I do this analytically, I get expected results:
f =
20.4818
-15.4784
8.3696
etc...
My question is: what am I doing wrong with the fft() function to give me such weird results? How can I fix it to give me the actual Fourier coefficients?
2 个评论
Jan
2022-3-18
How did you solve this analytically? The problem is hidden there.
According to the documentation, FFT calculates:
N
X(k) = sum x(n)*exp(-j*2*pi*(k-1)*(n-1)/N), 1 <= k <= N.
n=1
Especially X(1) equals sum(f), so 1.1047e3 is the expected result.
Paul
2022-3-20
If you don't mind my asking, do you have to use the FFT for this problem? The FFT only yields an approximation to the alpha(k), but the exact form of alpha(k) is readily computed as shown below.
采纳的回答
Star Strider
2022-3-18
It is possible to get close to the desired result by ‘adjusting’ the fft arguments —
n = 50;
f = linspace(-pi, pi, n); % Establish domain
f = f.^4 + 1; % Calculate f(theta)
f = fft(f,(n-1))/(n-1) % FFT NOTE: Need To Divide By 'n'
syms f(theta) k theta % Analytic Computation
f(theta) = theta^4 + 1
F(k) = int(f*exp(-1j*k*theta), theta, -pi, pi)/(2*pi)
F = simplify(F, 500)
kv = sym(1E-50:49);
Fv = double(F(kv))
.
6 个评论
Walter Roberson
2022-3-20
It is common for people to build a periodic signal that ends returning to the starting point. For example a triangle that starts and ends with 0. But fft treats the input as indefinitely repeatable, and if you put two cycles of the data together then in the middle you would have the 0 from the end of the signal and then another zero from the beginning, giving you two zeros in a row when there should only be one. Thus you need your signal to end one sample earlier than you would normally expect.
I typically construct the signal as returning, but then throw away the last sample.
更多回答(1 个)
Paul
2022-3-18
Define the function to evaluate f(theta)
ffunc = @(theta) (theta.^4 + 1); % only valid between -pi and pi, zero otherwise
Define a function to evaluate the periodic extension of f(theta) with period 2*pi.
ffuncext = @(theta) ffunc(mod(theta + pi,2*pi) - pi); % periodic extension
We want to use the DFT (via fft()) to compute the discrete Fourier series coefficients of a sequence of samples of f(theta). Those coefficients approximate alpha_k, which are the continuous Fourier series coefficients of f(theta).
In order for this to go smoothly, the sampling period in theta has to be 2*pi/N, where N is an integer. Then we can take N samples of theta and compute the N-point DFT. However, recall that the upper half of the DFT actually corresponds to frequencies from -pi to 0, which correspond to negative values of k. The problem statement only asks for alpha(k) for k = 0:n-1. So we have to choose N to be 2*(n-1), and then only use the first N/2 values of the DFT. For example, let n - 1 = 49
n = 50;
N = 2*(n-1);
The DFT always assumes the first point in the sequence is at index = 0. So, in general, we either sample the function starting from theta = 0 or we can sample starting from theta = -pi and shift the resulting DFT. For this particular f(theta) it won't matter, but I prefer the former.
thetavals = (0:N-1)/N*2*pi; % N samples of theta over one period of f(theta)
Evaluate the function over one period
fvals = ffuncext(thetavals);
Compute the DFT and normalize
c_k = fft(fvals)/N; % normalized
Compute the exact result
syms f(theta) k
f(theta) = theta^4 + 1;
alpha(k) = simplify(int(f*exp(-1j*k*theta), theta, -pi, pi)/(2*sym(pi)));
alpha(k) = piecewise(k == 0, limit(alpha(k),k,0),alpha(k));
Compare the approximate solution and the exact solution
kvals = 0:n-1;
alphavals = double(alpha(kvals));
figure
stem(kvals(1:n),real(c_k(1:n)))
hold on;
stem(kvals,real(alphavals),'x')
figure
stem(kvals(1:n),imag(c_k(1:n)))
hold on
stem(kvals,imag(alphavals),'x')
Sampling doesn't come for free. The cost is that the c_k only approximate the alpha_k, and the approximation becomes worse for smaller n (fewer samples) and as k inreases towards the Nyquist frequency.
figure
stem(kvals(1:n),abs(c_k(1:n) - alphavals))
0 个评论
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Bartlett 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!




