别再死记硬背了!用Python的Matplotlib亲手画一遍sinx、cosx、tanx等函数图像,理解更深刻
用Python动态绘制三角函数:从数学抽象到代码实践
三角函数是数学中的基础概念,但传统的静态教材图像往往难以直观展示其动态特性。本文将带你用Python的Matplotlib库亲手绘制sinx、cosx、tanx等函数图像,通过代码实现数学概念的可视化,让抽象理论变得触手可及。
1. 环境准备与基础绘图
1.1 搭建Python科学计算环境
推荐使用Anaconda发行版,它预装了NumPy、Matplotlib等科学计算库。安装完成后,创建一个新的Jupyter Notebook:
conda create -n trig_visualization python=3.9 conda activate trig_visualization conda install numpy matplotlib jupyter jupyter notebook1.2 绘制第一个正弦函数
让我们从最简单的正弦函数开始。在Jupyter Notebook中新建单元格,输入以下代码:
import numpy as np import matplotlib.pyplot as plt x = np.linspace(-2*np.pi, 2*np.pi, 1000) y = np.sin(x) plt.figure(figsize=(10, 6)) plt.plot(x, y, label='sin(x)', color='blue') plt.title('正弦函数 sin(x)') plt.xlabel('x (radians)') plt.ylabel('sin(x)') plt.grid(True) plt.axhline(y=0, color='black', linewidth=0.5) plt.axvline(x=0, color='black', linewidth=0.5) plt.legend() plt.show()这段代码会生成一个从-2π到2π区间内的正弦函数图像。关键参数说明:
np.linspace():在指定范围内生成均匀分布的点figsize:控制图像大小grid(True):显示网格线axhline/axvline:绘制坐标轴
2. 探索三角函数家族
2.1 余弦函数与正弦函数的对比
在同一个坐标系中绘制sinx和cosx,可以直观比较它们的相位关系:
x = np.linspace(-2*np.pi, 2*np.pi, 1000) y_sin = np.sin(x) y_cos = np.cos(x) plt.figure(figsize=(10, 6)) plt.plot(x, y_sin, label='sin(x)', color='blue') plt.plot(x, y_cos, label='cos(x)', color='red', linestyle='--') plt.title('正弦与余弦函数对比') plt.xlabel('x (radians)') plt.ylabel('y') plt.grid(True) plt.legend() plt.show()提示:观察图像可以发现,余弦函数实际上是正弦函数向左平移π/2个单位的结果,即cos(x) = sin(x + π/2)。
2.2 正切函数的特殊性质
正切函数tanx = sinx/cosx在cosx=0的点(如x=π/2+kπ)处无定义,图像会出现渐近线:
x = np.linspace(-2*np.pi, 2*np.pi, 1000) y_tan = np.tan(x) # 避免在渐近线附近绘制过大的值 y_tan[np.abs(y_tan) > 10] = np.nan plt.figure(figsize=(10, 6)) plt.plot(x, y_tan, label='tan(x)', color='green') plt.title('正切函数 tan(x)') plt.xlabel('x (radians)') plt.ylabel('tan(x)') plt.ylim(-5, 5) plt.grid(True) plt.legend() plt.show()关键技巧:
- 使用
np.nan处理无穷大值,避免图像失真 ylim限制y轴范围,使图像更清晰
3. 高级可视化技巧
3.1 绘制三角函数族
将多个三角函数绘制在同一坐标系中,使用不同颜色和线型区分:
x = np.linspace(-2*np.pi, 2*np.pi, 1000) functions = { 'sin(x)': np.sin(x), 'cos(x)': np.cos(x), 'tan(x)': np.tan(x), 'sin(x)+cos(x)': np.sin(x) + np.cos(x) } plt.figure(figsize=(12, 7)) for name, y in functions.items(): if 'tan' in name: y_plot = y.copy() y_plot[np.abs(y_plot) > 10] = np.nan plt.plot(x, y_plot, label=name, linestyle='-.') else: plt.plot(x, y, label=name) plt.title('三角函数家族') plt.xlabel('x (radians)') plt.ylabel('y') plt.ylim(-3, 3) plt.grid(True) plt.legend() plt.show()3.2 交互式可视化
使用Matplotlib的交互模式,可以动态观察函数变化:
from matplotlib.widgets import Slider fig, ax = plt.subplots(figsize=(10, 6)) plt.subplots_adjust(bottom=0.25) x = np.linspace(-2*np.pi, 2*np.pi, 1000) a_init = 1.0 y = a_init * np.sin(x) line, = plt.plot(x, y, lw=2) plt.title('可调节振幅的正弦函数') plt.xlabel('x (radians)') plt.ylabel('y') plt.grid(True) ax_amp = plt.axes([0.25, 0.1, 0.65, 0.03]) amp_slider = Slider( ax=ax_amp, label='振幅', valmin=0.1, valmax=5.0, valinit=a_init ) def update(val): amp = amp_slider.val line.set_ydata(amp * np.sin(x)) fig.canvas.draw_idle() amp_slider.on_changed(update) plt.show()4. 数学原理与代码实现的结合
4.1 单位圆与三角函数关系
通过动画展示单位圆上点的运动与三角函数图像生成的关系:
from matplotlib.animation import FuncAnimation fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 6)) # 单位圆设置 circle = plt.Circle((0, 0), 1, fill=False, color='blue', linestyle='--', ax=ax1) ax1.add_patch(circle) ax1.set_xlim(-1.5, 1.5) ax1.set_ylim(-1.5, 1.5) ax1.set_aspect('equal') ax1.grid(True) ax1.set_title('单位圆') # 正弦函数图像设置 x = np.linspace(0, 2*np.pi, 200) y = np.sin(x) line, = ax2.plot(x, y, 'r-') point, = ax2.plot([], [], 'bo') ax2.set_xlim(0, 2*np.pi) ax2.set_ylim(-1.5, 1.5) ax2.grid(True) ax2.set_title('正弦函数') # 动画更新函数 def update(frame): angle = frame * 2 * np.pi / 100 cos_val, sin_val = np.cos(angle), np.sin(angle) # 更新单位圆 ax1.clear() ax1.add_patch(plt.Circle((0, 0), 1, fill=False, color='blue', linestyle='--')) ax1.plot([0, cos_val], [0, sin_val], 'g-') ax1.plot([cos_val, cos_val], [0, sin_val], 'g--') ax1.plot(cos_val, sin_val, 'ro') ax1.set_xlim(-1.5, 1.5) ax1.set_ylim(-1.5, 1.5) ax1.set_aspect('equal') ax1.grid(True) ax1.set_title(f'角度: {np.degrees(angle):.1f}°') # 更新正弦曲线 current_x = x[:frame] current_y = y[:frame] line.set_data(current_x, current_y) if frame > 0: point.set_data(x[frame-1], y[frame-1]) return line, point ani = FuncAnimation(fig, update, frames=100, interval=50, blit=True) plt.show()4.2 三角函数的对称性与周期性分析
通过代码验证三角函数的性质:
def analyze_function(func, name): x = np.linspace(-2*np.pi, 2*np.pi, 1000) y = func(x) # 检查周期性 period = 2*np.pi if name in ['sin', 'cos'] else np.pi y_shifted = func(x + period) is_periodic = np.allclose(y, y_shifted, atol=1e-10) # 检查奇偶性 y_neg_x = func(-x) is_odd = np.allclose(y, -y_neg_x, atol=1e-10) is_even = np.allclose(y, y_neg_x, atol=1e-10) print(f"{name}函数分析:") print(f" 周期性: {'是' if is_periodic else '否'},周期≈{period/np.pi}π") print(f" 奇偶性: {'奇函数' if is_odd else '偶函数' if is_even else '非奇非偶'}") analyze_function(np.sin, 'sin') analyze_function(np.cos, 'cos') analyze_function(np.tan, 'tan')输出结果示例:
sin函数分析: 周期性: 是,周期≈2.0π 奇偶性: 奇函数 cos函数分析: 周期性: 是,周期≈2.0π 奇偶性: 偶函数 tan函数分析: 周期性: 是,周期≈1.0π 奇偶性: 奇函数5. 实际应用案例
5.1 信号处理中的三角函数应用
模拟简单的调幅信号(AM):
t = np.linspace(0, 4*np.pi, 1000) carrier_freq = 10 # 载波频率 signal_freq = 1 # 信号频率 carrier = np.sin(carrier_freq * t) signal = 0.5 * np.sin(signal_freq * t) am_wave = (1 + signal) * carrier plt.figure(figsize=(12, 8)) plt.subplot(3, 1, 1) plt.plot(t, signal, 'b') plt.title('原始信号') plt.grid(True) plt.subplot(3, 1, 2) plt.plot(t, carrier, 'g') plt.title('载波') plt.grid(True) plt.subplot(3, 1, 3) plt.plot(t, am_wave, 'r') plt.title('调幅信号(AM)') plt.grid(True) plt.tight_layout() plt.show()5.2 傅里叶级数可视化
展示方波如何由正弦波叠加而成:
def square_wave(x, n_terms): y = np.zeros_like(x) for n in range(1, n_terms+1, 2): y += (4/np.pi) * (1/n) * np.sin(n*x) return y x = np.linspace(-2*np.pi, 2*np.pi, 1000) plt.figure(figsize=(12, 6)) for i, n in enumerate([1, 3, 5, 10, 50], 1): plt.subplot(2, 3, i) y = square_wave(x, n) plt.plot(x, y) plt.title(f'{n}项近似') plt.ylim(-1.5, 1.5) plt.grid(True) plt.tight_layout() plt.show()在实际项目中,我发现当使用50项以上的正弦波叠加时,已经能够很好地近似方波信号。这种可视化方法对于理解傅里叶变换的本质非常有帮助。
