坑一:符号与变量

符号(Symbol)指的是SymPy提供的,用symbols()定义的符号,而变量是Python提供的。

1
2
3
4
5
>>> x = symbols('x')
>>> expr = x + 1
>>> x = 2
>>> print(expr)
x + 1

以上这个程序,并没有输出3,而是输出了x + 1,这是因为x = 2只是将变量x的值,从符号xx,变成了数字2,而符号xx并没有发生改变,因此expr的值也就没有改变。

想要计算expr在x=2条件下的值,可以使用subs:

1
2
3
4
>>> x = symbols('x')
>>> expr = x + 1
>>> expr.subs(x, 2)
3

坑二:等于号

假如你用==检测两个式子是否相等,你将会得到错误的结果:

1
2
>>> (x + 1)**2 == x**2 + 2*x + 1
False

SymPy并没有扩展Python的语法,=依然表示赋值,==表示变量的相等,因此在SymPy中,主要用这两种方式表示两个式子相等:

  1. 这是官方文档中推荐的方法:假如你想要验证a=ba = b是否成立,可以检测ab=0a - b = 0是否成立,只要将两个式子相减,然后使用simplify()函数化简,如果结果是0,则必定相等,如果不是0,大多数情况下不相等,但也存在极少数情况,式子确实为0,但是SymPy无法将其化简,对于常见的数学式子,可以放心地使用这个方法检验其是否相等。
1
2
3
4
5
6
7
>>> a = (x + 1)**2
>>> b = x**2 + 2*x + 1
>>> simplify(a - b)
0
>>> c = x**2 - 2*x + 1
>>> simplify(a - c)
4*x
  1. 另一种方法是使用a.equals(b),但是这个方法并不是使用式子的化简得到的结论,而是通过随机地给式子赋多个值,比较二者是否相等。
1
2
3
4
>>> a = cos(x)**2 - sin(x)**2
>>> b = cos(2*x)
>>> a.equals(b)
True

坑三:^符号

SymPy使用和Python一样的符号约定,用**表示指数,^表示异或(Xor),所以不应该尝试使用^表示指数。

1
2
>>> Xor(x, y)
x ^ y

坑四:/符号

两个SymPy对象相除,或者一个SymPy对象相除的时候,返回值都是SymPy对象,这没有问题。但是当分子分母都是Python的int时,要小心了。两个SymPy对象相除会返回一个分数,但是两个Python的int相除会返回一个浮点数(Python3)。

1
2
3
4
5
6
7
8
>>> x / y
x/y
>>> x / 19
x/19
>>> 3 / x
3/x
>>> 3 / 19
0.15789473684210525

0.15789473684210525不是我们想要的结果,这个值不是精确的,当处理两个整数相除的时候,可以使用Rational()来避免这种结果:

1
2
Rational(3, 19) 
3/19

如果和其他符号连接起来的时候这种错误就更难以察觉:

1
2
3
4
>>> x + 1/3
x + 0.333333333333333
>>> x + Rational(1, 3)
x + 1/3