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\]

需要置换的场景:

  1. 求解具体的表达式代表的值,比如:

expr.subs(x, 0)
\[\displaystyle 2\]
  1. 变量替换:

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

如果数据量很大,需要借助 NumPy 和 SciPy

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