SciPy 与 SymPy:数值算结果,符号推公式,各管各的
做科学计算的时候,你经常会遇到两种需求:
- 算一个具体的数:比如
∫₀¹ sin(x) dx = 0.4596... - 推一个数学公式:比如
∫ x·sin(x) dx = -x·cos(x) + sin(x)
前者是数值计算(SciPy 的活),后者是符号运算(SymPy 的活)。数值给结果,符号给表达式。 两套工具,解决两类问题。
数值积分:函数没原函数,或者数据来自实验
很多工程问题需要算积分,但被积函数可能没有初等原函数,或者数据是测量来的(离散点,没有表达式)。这时候用数值积分。
一维定积分:quad(最常用)
1 | from scipy.integrate import quad |
quad 返回两个值:积分结果和误差估计。误差估计别看小,它告诉你结果可不可信。 如果误差比结果还大,说明积分没收敛。
带参数的积分:
1 | def integrand(x, a, b): |
二重积分:dblquad(注意积分顺序)
1 | from scipy.integrate import dblquad |
注意: dblquad 的积分顺序跟数学表达式是反的。数学上写 ∫∫ f(x,y) dx dy,dblquad 里是先积 y 再积 x。搞反了结果完全不对。
三重及以上:nquad
1 | from scipy.integrate import nquad |
离散数据积分:数据是点,不是函数
实验数据往往是一堆 (x, y) 点,没有表达式。
1 | from scipy.integrate import simpson, trapezoid |
选哪个?
| 数据特点 | 用哪个 |
|---|---|
| 有解析函数 | quad(精度高,自动控制误差) |
| 均匀采样的离散点 | simpson(精度更高) |
| 不均匀采样的离散点 | trapezoid(只能用这个) |
常微分方程:odeint 模拟动态系统
物理系统常用微分方程描述,但解析解往往不存在。odeint 用数值方法(Runge-Kutta)近似求解。
洛伦茨吸引子(混沌的经典例子):
1 | from scipy.integrate import odeint |
几个实用建议:
- 时间步长要够密。 变化快的系统步长太大会不稳定。
- 刚性系统(快慢时间尺度共存)用
odeint的rtol和atol调精度,或者换solve_ivp的BDF方法。 odeint不支持事件检测(比如碰撞、触顶),这种情况用solve_ivp。
符号运算:让计算机帮你推公式(SymPy)
数值计算算的是”数”,符号运算算的是”式子”。
1 | from sympy import symbols, diff, integrate |
符号的假设条件会影响化简结果:
1 | from sympy import sqrt, simplify |
解微分方程(dsolve):
1 | from sympy import Function, dsolve, Eq |
实际场景:推导球体体积公式
1 | from sympy import symbols, integrate, sqrt |