Parseval’s Theorem Demo

Parseval’s theorem demo (DFT / FFT)

Build a length-N signal, optionally apply a window, and compute its energy two ways: directly in time as Σ|x[n]|², and from the FFT. The DFT has two common scalings, and the demo shows both: the ordinary (unnormalized) DFT needs a 1/N factor, the unitary DFT (divide by √N) does not. The ratio Etime/Efreq should be 1 to rounding error.

Loading…
Real-valued test signal. Energy is computed on the signal after the window (if any).
Powers of two so a radix-2 FFT applies. Bin spacing is fs/N.
Multiplies x[n] by w[n] before the FFT. Parseval then holds for the windowed sequence.
Changes only the lower plot and its height. Both energies are always reported below.
Only for Rectangular pulse. Fraction of the record that is 1 (starts at N/4).
Only for Tone. Integer = exactly on a bin; a fraction (e.g. 8.5) leaks across bins but Parseval still holds.
Only for Gaussian pulse. Width of the pulse, centered at N/2. Narrow in time means wide in frequency.
Only for White noise. Same seed gives the same realization (shareable).
Time domain: Etime = Σ |x[n]|² —
Ordinary DFT: (1/N) Σ |X[k]|² —
Unitary DFT: Σ |Xu[k]|², Xu = X/√N —
Ratio Etime / Efreq (ordinary, with 1/N) —
Ratio Etime / Efreq (unitary) —
Worst relative error |ratio − 1| —
Common bug: forget 1/N, Etime / Σ|X[k]|² —
Average power P = E/N and RMS = √P —
Window ENBW = N Σw² / (Σw)² (bins) —

|x[n]| after windowing

|X[k]|

Try this: leave everything on defaults and note the ratio is 1.000000000000. Switch the plot between ordinary and unitary: the spectrum height changes by √N, yet both energies match Etime. Then read the amber “common bug” row: without the 1/N the answer is off by exactly a factor of N.

Windows: set Signal = Tone, frequency 8.5, then toggle Hann. Leakage drops, Etime drops too (the window removes energy), but Parseval still balances on the windowed data.

Background articles: Parseval’s theorem derivation · Power and energy of a signal · Significance of RMS value.

Controls explained

Signal
Rectangular pulse — a block of ones (spectrum is a sampled sinc). Tone — cos(2πfn/N); a bin-centered tone puts all energy in two bins (k = f and N−f). Gaussian pulse — smooth, its spectrum is also Gaussian. White noise — independent N(0,1) samples; energy is about N and spreads evenly over bins.
Samples N
Record length. Energy grows with N for a fixed signal shape (more samples to sum), and the unnormalized |X[k]| grows too. The 1/N in Parseval is exactly what reconciles them.
Window
Rectangular leaves x[n] untouched. Hann multiplies by w[n] = 0.5(1 − cos(2πn/N)). The reported energies are those of x[n]·w[n], not of x[n]. ENBW (equivalent noise bandwidth) is NΣw²/(Σw)²: 1.00 bin for rectangular, 1.50 bins for Hann.
Plot |X[k]| using
Ordinary is what numpy.fft.fft, MATLAB fft, and most libraries return. Unitary divides by √N (the norm="ortho" option in NumPy), so that Σ|Xu|² = Σ|x|² with no extra factor. Only the lower plot is affected.
Pulse width / Tone frequency / Gaussian σ / Noise seed
Signal-specific shape parameters. Each is hidden when it does not apply to the selected signal. None of them can break Parseval; they only change how the same energy is distributed over time and frequency.
Results panel
The two ratios should equal 1 up to floating-point rounding (relative error near 1e−15). The “common bug” row shows what you get if you sum |X[k]|² and forget the 1/N: the ratio is exactly 1/N.

How to use this demo

Pick a signal, choose N, and read the results panel. The top rows give the time-domain energy Σ|x[n]|² and the frequency-domain energy computed from the FFT under both common scalings: (1/N)Σ|X[k]|² for the ordinary DFT and Σ|Xu[k]|² for the unitary DFT. Both ratios sit at 1 up to rounding. The amber row shows the classic mistake of summing |X[k]|² without the 1/N.

Quick checks: white noise, N = 1024 (the forgotten-1/N error is now 1/1024), and a leaky tone with a Hann window.

Read next

FAQ

Why is my energy N times too big? You summed |X[k]|² from an unnormalized FFT. Divide by N, or use the unitary (norm="ortho") transform.

Why doesn’t the ratio hit exactly 1? Floating-point rounding. Expect a relative error around 1e−15 to 1e−13, growing slightly with N.

Does a window break Parseval? No. Parseval applies to whatever sequence you hand to the FFT. After windowing, that sequence is x[n]·w[n], so its energy is lower than the original signal’s.

Why do fractional tone frequencies still satisfy Parseval? Leakage spreads the energy over many bins, but the total over all N bins is unchanged. Leakage affects where the energy shows up, not how much there is.