Python手动实现加速度数据傅里叶变换积分的报错问题求助
手动实现离散傅里叶变换(DFT):解决你的代码错误与原理解析
Hey there! 完全理解你想通过手动实现吃透傅里叶变换原理的需求——课程要求确实是个绝佳的契机,咱们一步步把你代码里的问题解决掉,顺便把DFT的核心逻辑理清楚。
你的代码里的两个核心问题
1. 列表索引越界错误
你初始化了Int_UD = [],然后在第一次循环(i=0)的时候尝试访问Int_UD[i-1]也就是Int_UD[-1]——但这时候列表是空的,自然会抛出索引越界的错误。更关键的是,这个循环的逻辑和离散傅里叶变换(DFT)的计算逻辑完全不匹配:DFT是对每个频率点,计算所有采样点的加权求和,而不是逐个采样点累加结果。
2. 复数类型警告
你把w定义成了一个包含浮点数的列表,虽然Python在计算ri * w时会自动把浮点数转成复数,但静态类型检查工具(比如PyCharm)会因为列表元素类型不是复数而发出警告。解决这个问题的方式很简单:把w改成numpy数组,或者直接在计算时生成复数形式的频率项。
手动实现DFT的正确思路(结合你的需求)
首先得明确:你的加速度数据UD_Acc是离散采样的,所以我们需要实现离散傅里叶变换(DFT),而不是连续傅里叶变换的积分形式。DFT的核心公式是:
X[k] = Σ(n=0到N-1) x[n] * e^(-j * 2π * k * n / N)
其中:
x[n]是第n个采样点的加速度值(对应你的UD_Acc[n])N是总采样点数(UD_Acc.size)k是频率点索引,对应频率f_k = k * F_s / N,F_s = 1/dt1是采样频率j是虚数单位(你代码里的ri)
现在我们把这个公式转换成代码,同时解决你的问题:
修正后的代码
import numpy as np # 初始化虚数单位 ri = 1j # 采样间隔(假设你已经定义过dt1,这里给个示例值) # dt1 = 0.001 # 比如1ms的采样间隔 Fs = 1 / dt1 # 采样频率 N = UD_Acc.size # 总采样点数 # 你的频率参数设定 Fmax = 50 # Hz,最大关注频率 df = 0.01 # 频率步长 nf = int(Fmax / df) # 频率点数量 # 生成目标频率数组,同时直接生成复数形式的角频率项(解决类型警告) freqs = np.arange(0, Fmax, df) # DFT中是e^(-jωt),所以这里直接生成-2πf*j的形式 omega = -2 * np.pi * freqs * ri # 初始化傅里叶变换结果数组(复数类型) FT_UD = np.zeros(nf, dtype=np.complex128) # 手动计算DFT:外层遍历频率点,内层遍历所有采样点求和 for k in range(nf): current_omega = omega[k] sum_result = 0j for n in range(N): # 每个采样点的加权项:x[n] * e^(-jω*t_n),t_n = n*dt1是采样时间 sum_result += UD_Acc[n] * np.exp(current_omega * n * dt1) FT_UD[k] = sum_result
代码解释
- 解决类型警告:直接用numpy生成复数类型的角频率数组
omega,彻底消除类型检查工具的警告。 - 修正索引越界:抛弃原来错误的累加逻辑,改用DFT的标准双重循环——外层循环遍历每个频率点,内层循环遍历所有采样点计算加权求和,从根源避免索引问题。
- 贴合你的需求:完全保留了你设定的
Fmax和df参数,生成你需要的频率范围的傅里叶变换结果。
额外的优化建议(可选)
如果你的采样点数很多,嵌套循环会比较慢,你可以用numpy的向量化操作来加速(但依然是手动实现,没有用np.fft.fft):
# 生成所有采样点的时间数组 t = np.arange(N) * dt1 # 用列表推导式结合向量化运算,替代嵌套循环,速度更快 FT_UD = np.array([np.sum(UD_Acc * np.exp(-2 * np.pi * ri * f * t)) for f in freqs])
这个版本依然严格遵循DFT的核心逻辑,但利用numpy的向量化特性大幅提升了计算效率。
内容的提问来源于stack exchange,提问作者greenrabbit
相关产品推荐
相关产品推荐

