梯形法求积分的Python实现

学会了函数,也学会了循环、分支、流程,其实就可以做很多事情了,至少可以拿来解决很多数据相关的问题。比如,求函数的积分。

什么是数值积分?

在数学中,积分是求解函数曲线下面积的重要工具,计算方法可以为解析法和数值法。 简单来说,解析法就是求出原函数,然后来用上下界代入计算,就得到了。 数值法则简单粗暴,就是对付着近似一下,只要近似的精度达到要求就可以。 有很多函数都有原函数,但在实际应用中,有些函数的原函数形式复杂,与其求原函数,不如用数值方法来计算。 再比如可能有的同学像我一样就是不会求原函数,或者懒得算,那我就写代码来算显得厉害等等因素,可以使用数值方法来近似计算积分值。 梯形法就是一种简单而有效的数值积分方法。

梯形法的基本思路

梯形法的核心思想是"化曲为直",将复杂的曲线用简单的直线来近似:

1.分割区间:将积分区间 [a,b] 分成 n 个等宽的小段2.近似替代:在每个小段上,用梯形面积代替曲边梯形面积3.求和累加:将所有梯形面积相加,得到积分的近似值

Image

数学原理

对于函数 f(x) 在区间 [a,b] 上的定积分,梯形法的公式为:

∫[a,b] f(x)dx ≈ (b-a)/2n * [f(x₀) + 2f(x₁) + 2f(x₂) + ... + 2f(xₙ₋₁) + f(xₙ)]

其中:

•n 是分割的区间数•h = (b-a)/n 是每个小区间的宽度•xᵢ = a + i*h 是第 i 个分割点

梯形面积计算

每个小梯形的面积计算公式为: 第 i 个梯形面积 = [f(xᵢ) + f(xᵢ₊₁)] * h / 2

这其实就是我们熟悉的梯形面积公式:(上底 + 下底) × 高 ÷ 2

Python代码实现解析

让我们通过一个具体的Python代码示例来理解梯形法的实现过程。

被积函数定义

def f(x):    """被积函数: f(x) = x * exp(x) - 2"""    return x * np.exp(x) - 2

我们选择的被积函数是 f(x) = x * e^x - 2,我们用它来演示梯形法的效果,并与解析解进行对比验证。

该函数的原函数为: F(x) = (x-1) * e^x - 2x + C

因此定积分的解析解为: ∫[a,b] (x * e^x - 2) dx = [(x-1) * e^x - 2x]ₐᵇ                         = [(b-1) * e^b - 2b] - [(a-1) * e^a - 2a]

梯形法实现步骤

#!/usr/bin/env python3# -*- coding: utf-8 -*-import numpy as npimport matplotlib.pyplot as pltfrom matplotlib.animation import FuncAnimationfrom matplotlib.patches import Polygon
# 配置中文字体plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei']plt.rcParams['axes.unicode_minus'] = False
def f(x):    """被积函数: f(x) = x * exp(x) - 2"""    return x * np.exp(x) - 2
def trapezoidal_animate_process(f, a, b, n):    """        参数:        f: 被积函数        a: 积分下限        b: 积分上限        n: 分割区间数    """    # 计算分割点和函数值    x_points = np.linspace(a, b, n+1)    y_points = f(x_points)
    # 计算每一步的梯形面积和累积面积    h = (b - a) / n    steps = []    cumulative_area = 0
    for i in range(n):        # 当前梯形的四个顶点        x_left, x_right = x_points[i], x_points[i+1]        y_left, y_right = y_points[i], y_points[i+1]
        # 梯形面积计算        trap_area = (y_left + y_right) * h / 2        cumulative_area += trap_area
        steps.append({            'x_left': x_left,            'x_right': x_right,            'y_left': y_left,            'y_right': y_right,            'area': trap_area,            'cumulative': cumulative_area        })
    # 创建图形    fig, ax = plt.subplots(figsize=(12, 8))
    # 绘制完整的函数曲线    x_curve = np.linspace(a-0.5, b+0.5, 1000)    y_curve = f(x_curve)    ax.plot(x_curve, y_curve, 'b-', linewidth=2, label='$f(x) = x e^x - 2$')
    # 填充真实的积分区域    x_fill = np.linspace(a, b, 1000)    y_fill = f(x_fill)    ax.fill_between(x_fill, 0, y_fill, alpha=0.3, color='lightblue', label='真实积分区域')
    # 绘制坐标轴    ax.axhline(0, color='black', linewidth=0.8)    ax.axvline(0, color='black', linewidth=0.8)    ax.axvline(a, color='green', linestyle='--', linewidth=1.2, label=f'下限 a = {a}')    ax.axvline(b, color='green', linestyle='--', linewidth=1.2, label=f'上限 b = {b}')
    # 设置图形属性    ax.set_xlim(a-0.5, b+0.5)    y_min, y_max = np.min(y_curve), np.max(y_curve)    ax.set_ylim(y_min-0.5, y_max+1)    ax.set_xlabel('x', fontsize=12)    ax.set_ylabel('f(x)', fontsize=12)    ax.set_title('梯形法则数值积分动画演示', fontsize=16)    ax.legend(fontsize=11)    ax.grid(True, alpha=0.3)
    # 添加说明文本    info_text = ax.text(0.02, 0.98, '', transform=ax.transAxes, fontsize=11,                       verticalalignment='top',                       bbox=dict(boxstyle="round,pad=0.3", facecolor="yellow", alpha=0.7))
    # 存储已绘制的梯形    trapezoids = []
    def animate(frame):        """动画函数"""        # 清除之前的梯形(除了第一帧)        if frame > 0 and frame <= len(steps):            # 移除上一个梯形            if trapezoids:                trapezoids[-1].remove()                trapezoids.pop()
        # 如果是最后一帧,显示所有梯形并停止        if frame >= len(steps):            # 显示所有梯形            for step in steps:                vertices = [                    (step['x_left'], 0),                    (step['x_left'], step['y_left']),                    (step['x_right'], step['y_right']),                    (step['x_right'], 0)                ]                trap = Polygon(vertices, closed=True, facecolor='red', alpha=0.5, edgecolor='red')                ax.add_patch(trap)                trapezoids.append(trap)
            info_text.set_text(f'梯形法则积分完成\n'                              f'分割数: {n}\n'                              f'最终结果: {steps[-1]["cumulative"]:.6f}')            return trapezoids + [info_text]
        # 获取当前步骤        step = steps[frame]
        # 绘制当前梯形        vertices = [            (step['x_left'], 0),            (step['x_left'], step['y_left']),            (step['x_right'], step['y_right']),            (step['x_right'], 0)        ]        trap = Polygon(vertices, closed=True, facecolor='red', alpha=0.3, edgecolor='red', linewidth=2)        ax.add_patch(trap)        trapezoids.append(trap)
        # 更新信息文本        info_text.set_text(f'第 {frame+1} 个梯形\n'                          f'区间: [{step["x_left"]:.2f}, {step["x_right"]:.2f}]\n'                          f'面积: {step["area"]:.6f}\n'                          f'累积: {step["cumulative"]:.6f}')
        return trapezoids + [info_text]
    # 创建动画    anim = FuncAnimation(fig, animate, frames=len(steps)+20, interval=1000, repeat=True)
    plt.tight_layout()    plt.show()
    return anim, steps[-1]['cumulative'] if steps else 0
def compare_accuracy(f, a, b, n_values):    """    比较不同分割数下的积分精度
    参数:        f: 被积函数        a: 积分下限        b: 积分上限        n_values: 分割数列表    """    print(f"\n精度比较 (积分区间 [{a}, {b}]):")    print("-" * 50)    print(f"{'分割数':<8} {'积分结果':<15} {'误差':<15}")    print("-" * 50)
    # 计算解析解(用于比较)      # (x * e^x - 2)dx = (x-1) * e^x - 2x + C    analytical = (b-1) * np.exp(b) - 2*b - ((a-1) * np.exp(a) - 2*a)
    for n in n_values:        # 数值积分        x = np.linspace(a, b, n+1)        y = f(x)        h = (b - a) / n        numerical = h * (0.5 * y[0] + np.sum(y[1:-1]) + 0.5 * y[-1])
        # 计算误差        error = abs(numerical - analytical)
        print(f"{n:<8} {numerical:<15.8f} {error:<15.2e}")
    print("-" * 50)    print(f"解析解: {analytical:.8f}")
# 主程序if __name__ == "__main__":        # 设置参数    a, b = 1, 4  # 积分区间    n = 10       # 分割数    # 创建动画    anim, result = trapezoidal_animate_process(f, a, b, n)    print(f"数值积分结果: {result:.8f}")

预览时标签不可点

Close

更多

Name cleared

微信扫一扫赞赏作者

Like the AuthorOther Amount

赞赏后展示我的头像

作品

暂无作品

Like the Author

Other Amount

¥

最低赞赏 ¥0

OK

Back

Other Amount

更多

赞赏金额

¥

最低赞赏 ¥0

1

2

3

4

5

6

7

8

9

0

.

Python语言程序设计 · 目录

Python语言程序设计

上一篇牛顿法求解过程的Python实现及其详解下一篇借助Python来理解自适应辛普森积分:原理、实现与动态可视化

Close

更多

搜索「」网络结果

Close

调整当前正文文字大小

更多

100%