1.1.2. 基本运算¶
定义一些基本数学变量:
import warnings
from sympy import *
warnings.filterwarnings('ignore')
# init_printing()
x, y, z = symbols('x y z')
置换¶
置换(substitution)即把某个变量替换为另一个变量。使用 subs
方法实现:
expr = cos(x) + 1
expr.subs(x, y) # x 置换为 y
\[\displaystyle \cos{\left(y \right)} + 1\]
需要置换的场景:
求解具体的表达式代表的值,比如:
expr.subs(x, 0)
\[\displaystyle 2\]
变量替换:
expr = x**y
expr = expr.subs(y, x**y)
expr
\[\displaystyle x^{x^{y}}\]
expr = expr.subs(y, x**x)
expr
\[\displaystyle x^{x^{x^{x}}}\]
expr = sin(2*x) + cos(2*x)
expand_trig(expr) # 三角展开
\[\displaystyle 2 \sin{\left(x \right)} \cos{\left(x \right)} + 2 \cos^{2}{\left(x \right)} - 1\]
expr.subs(sin(2*x), 2*sin(x)*cos(x))
\[\displaystyle 2 \sin{\left(x \right)} \cos{\left(x \right)} + \cos{\left(2 x \right)}\]
小技巧
SymPy 表达式是不可变的对象。
替换多个变量可以这样:
expr = x**3 + 4*x*y - z
expr.subs([(x, 2), (y, 4), (z, 0)])
\[\displaystyle 40\]
甚至,可以制定替换的规则:
expr = x**4 - 4*x**3 + 4*x**2 - 2*x + 3
replacements = [(x**i, y**i) for i in range(5) if i % 2 == 0]
expr.subs(replacements)
\[\displaystyle - 4 x^{3} - 2 x + y^{4} + 4 y^{2} + 3\]
转换字符串为 SymPy 表达式¶
sympify
可以将字符串转换为 SymPy 表达式:
str_expr = "x**2 + 3*x - 1/2"
expr = sympify(str_expr)
expr
\[\displaystyle x^{2} + 3 x - \frac{1}{2}\]
expr.subs(x, 2)
\[\displaystyle \frac{19}{2}\]
evalf
¶
evalf
将数值表达式转换为浮点数:
expr = sqrt(8)
expr.evalf()
\[\displaystyle 2.82842712474619\]
可以浮点数设置精确的位数:
pi.evalf(100)
\[\displaystyle 3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117068\]
为了精确的计算数值表达式,可以这样:
expr = cos(2*x)
expr.evalf(subs={x: 2.4})
\[\displaystyle 0.0874989834394464\]
有时舍入误差小于期望精度,可能会这样:
one = cos(1)**2 + sin(1)**2
(one - 1).evalf()
\[\displaystyle -4.0 \cdot 10^{-124}\]
此时,可以:
(one - 1).evalf(chop=True)
\[\displaystyle 0\]
lambdify
¶
import numpy as np
a = np.arange(10)
expr = sin(x)
f = lambdify(x, expr, "numpy")
f(a)
array([ 0. , 0.84147098, 0.90929743, 0.14112001, -0.7568025 ,
-0.95892427, -0.2794155 , 0.6569866 , 0.98935825, 0.41211849])
也可以自定义数值计算函数:
def mysin(x):
"""
My sine. Note that this is only accurate for small x.
"""
return np.sin(x)
f = lambdify(x, expr, {"sin":mysin})
f(0.1)
0.09983341664682815