如何用Python和Numpy精准生成指定起止值的缩放正弦波
解决正弦波起止值精准控制的数学方法
首先明确核心矛盾:严格的f个完整正弦周期必然导致起点和终点的y值相等,因为正弦函数的周期性($\sin(\phi + 2\pi k) = \sin\phi$,k为整数)。如果需要起点(start)和终点(stop)值不同,我们可以生成接近f个周期的正弦波(当采样点足够多时,视觉上与完整f个周期无差异),同时通过求解相位$\phi$满足起止值要求。
数学推导
正弦波的标准形式为:
$$ y(t) = A + B \cdot \sin(\omega t + \phi) $$
其中:
- $A = \frac{\text{max} + \text{min}}{2}$:直流偏移,保证波形均值在min和max的中点
- $B = \frac{\text{max} - \text{min}}{2}$:振幅,保证波形范围恰好是[min, max]
- $\omega = f$:对应原代码中t的范围为$0\sim2\pi$,确保采样范围内包含接近$f$个周期
我们需要满足两个边界条件:
- 当$t=0$时,$y(0) = \text{start}$ → $\sin(\phi) = \frac{\text{start} - A}{B}$
- 当$t=T_{\text{end}}$(即最后一个采样点的时间,原代码中为$2\pi \cdot \frac{999}{1000}$)时,$y(T_{\text{end}}) = \text{stop}$ → $\sin(f \cdot T_{\text{end}} + \phi) = \frac{\text{stop} - A}{B}$
通过求解这两个方程,可以得到唯一的相位$\phi$(需保证start和stop在[min, max]范围内,否则无解)。
实现代码
import numpy as np import matplotlib.pylab as plt # 参数设置 min_val = 0 max_val = 180 f = 2 # 接近完整f个周期 start = 45 stop = 60 num_points = 1000 # 采样点数 # 计算直流偏移和振幅 A = (max_val + min_val) / 2 B = (max_val - min_val) / 2 # 计算边界条件对应的正弦值 s_start = (start - A) / B s_stop = (stop - A) / B # 检查参数合法性:start和stop必须在波形范围内 assert abs(s_start) <= 1.0 + 1e-6, "start值超出波形范围" assert abs(s_stop) <= 1.0 + 1e-6, "stop值超出波形范围" # 生成时间序列 t = np.linspace(0, 2 * np.pi, num_points) # 最后一个点的总相位增量 phase_end = f * t[-1] # 求解相位φ的候选值 phi1 = np.arcsin(s_start) phi2 = np.pi - phi1 # 验证哪个候选值满足终点条件 def check_phi(phi): return np.abs(np.sin(phase_end + phi) - s_stop) < 1e-6 if check_phi(phi1): phi = phi1 elif check_phi(phi2): phi = phi2 else: # 尝试加2π周期寻找正确解 phi1 += 2 * np.pi phi = phi1 if check_phi(phi1) else phi2 + 2 * np.pi # 生成正弦波 y = A + B * np.sin(f * t + phi) # 验证结果 actual_min, actual_max = np.min(y), np.max(y) actual_start, actual_stop = y[0], y[-1] print(f"min: {actual_min:.6f}, max: {actual_max:.6f}") print(f"start: {actual_start:.6f}, stop: {actual_stop:.6f}") plt.plot(t, y) plt.title(f"Sine Wave with start={start}, stop={stop}, {f} cycles") plt.xlabel("t") plt.ylabel("y") plt.grid(True) plt.show()
代码说明
- 参数合法性检查:确保start和stop在波形的[min_val, max_val]范围内,否则无法生成符合要求的正弦波。
- 相位求解:利用反正弦函数得到两个候选相位,再验证哪个满足终点条件,必要时增加2π周期以找到正确解。
- 接近完整周期:由于采样点数量足够大(1000),最后一个点的相位与完整f个周期的相位差异极小,视觉上完全呈现f个周期的波形。
运行结果示例
min: 0.000000, max: 180.000000 start: 45.000000, stop: 60.000000
这样生成的波形既保证了振幅、接近f个周期的要求,又精准满足了起止值的设定,完全避免了裁剪数组的不优雅方案。
内容的提问来源于stack exchange,提问作者Matteo Caprari
相关产品推荐
相关产品推荐

