自定义逆傅里叶变换函数无法还原原正弦波,求排查问题
Let's break down why your custom IFT function isn't reconstructing the original sine wave correctly, and fix it step by step:
1. Mixed-Up Dimensions for Time/Frequency
Your original signal has 1000 time points (since time = np.arange(0, 1e6, 1000) gives 1000 samples), but your DFT output (fft) has 500 frequency points (from freq = np.arange(0, 0.05, 0.0001)).
In your IFT function:
- You set
N = fft.size(500) as the length of the time series, which is wrong—we need to generate a time series matching the original signal length (1000), not the number of frequency bins. - You initialized
inverse_fourierto lengthk = frequencies.size(500), but the IFT output should match the original signal's length, not the frequency count.
2. Wrong Sign in the Exponential
The standard inverse Fourier transform uses a positive exponential term, but your code uses -2j*np.pi*frequencies[i]*n/N. This flips the phase entirely, making it impossible to reconstruct the correct time-domain signal.
3. Incorrect Frequency-Time Mapping
Your DFT uses actual frequency values (frequencies[i]) multiplied by time points (t), not normalized frequencies (like k/N). However, your IFT incorrectly adds a /N scaling to the exponential term, which breaks the frequency-time correspondence.
4. Missing Scaling Factor
Your DFT includes a (1/k) scaling factor in the calculation. For the forward and inverse transforms to form a closed loop, the IFT needs a corresponding scaling adjustment—otherwise, the amplitude of the reconstructed signal will be wrong.
Fixed IFT Function
Here's the corrected version that addresses all these issues:
def IFT(fft, frequencies, original_signal_length): # original_signal_length = number of time points in the original signal (1000 here) num_time_points = original_signal_length num_freq_bins = fft.size # Generate the same time points as the original signal t = np.arange(num_time_points) # Use complex dtype to preserve phase information (critical for reconstruction) inverse_fourier = np.zeros(num_time_points, dtype=np.complex128) for i in range(num_time_points): # Positive exponential, no extra /N scaling (using actual frequencies) inverse_fourier[i] = np.dot(fft, np.exp(2j * np.pi * frequencies * t[i])) # Match the scaling from your DFT (1/k in forward → multiply by k here, or adjust to standard definitions) inverse_fourier = inverse_fourier * (1 / num_freq_bins) return inverse_fourier
Test the Reconstruction
To verify it works, run this code:
# Compute DFT of the original signal fft_result = DFT(signal, freq) # Reconstruct the signal using the fixed IFT recovered_signal = IFT(fft_result, freq, signal.size) # Plot original vs reconstructed signal import matplotlib.pyplot as plt plt.figure(figsize=(12, 6)) plt.plot(time, signal, label='Original Sine Wave', alpha=0.6) plt.plot(time, np.real(recovered_signal), label='Reconstructed Wave', linestyle='--') plt.xlabel('Time') plt.title('Original vs Reconstructed Signal') plt.legend() plt.grid(True) plt.show()
You'll see the reconstructed signal aligns almost perfectly with the original (minor discrepancies are normal for this approximate DFT implementation).
Side note: Your original DFT deviates slightly from the standard definition (which doesn't include the 1/k scaling—usually scaling is applied in the inverse transform). But as long as the forward and inverse scaling factors are paired, the loop will close correctly. If you want to align with standard DFT/IDFT, remove the (1/k) from your DFT and add (1/num_time_points) to the IFT instead.
内容的提问来源于stack exchange,提问作者wabash

