# SymPy 教程

> 原文： [http://zetcode.com/python/sympy/](http://zetcode.com/python/sympy/)

SymPy 教程展示了如何使用 SymPy 模块在 Python 中进行符号计算。 这是对 SymPy 的简要介绍。

计算机代数系统（CAS）是一种数学软件，能够以类似于数学家和科学家的传统手动计算方式来处理数学表达式。

符号计算象征性地处理数学对象的计算。 数学对象是准确而非近似地表示的，具有未求值变量的数学表达式以符号形式保留。

## SymPy

SymPy 是用于符号数学的 Python 库。 它旨在成为功能齐全的计算机代数系统。 SymPy 包括从基本符号算术到微积分，代数，离散数学和量子物理学的功能。 它可以在 LaTeX 中显示结果。

```py
$ pip install sympy

```

SymPy 是使用`pip install sympy`命令安装的。

## `Rational`值

SymPy 具有用于处理有理数的`Rational`。 有理数是可以表示为两个整数（分子`p`和非零分母`q`）的商或分数`p / q`的任何数字。

`rational_values.py`

```py
#!/usr/bin/env python

from sympy import Rational

r1 = Rational(1/10)
r2 = Rational(1/10)
r3 = Rational(1/10)

val = (r1 + r2 + r3) * 3
print(val.evalf())

val2 = (1/10 + 1/10 + 1/10) * 3
print(val2)

```

该示例使用有理数。

```py
val = (r1 + r2 + r3) * 3
print(val.evalf())

```

该表达形式为符号形式。 我们使用`evalf()`方法对其进行求值。

```py
$ rational_values.py
0.900000000000000
0.9000000000000001

```

注意，当不使用有理数时，输出中会有一个小错误。

## SymPy `pprint`

`pprint()`用于在控制台上精美打印输出。 LaTeX 可以达到最佳效果，例如在 Jupyter 笔记本中。

`prettify.py`

```py
#!/usr/bin/env python

from sympy import pprint, Symbol, exp, sqrt
from sympy import init_printing

init_printing(use_unicode=True)

x = Symbol('x')

a = sqrt(2)
pprint(a)
print(a)

print("------------------------")

c = (exp(x) ** 2)/2
pprint(c)
print(c)

```

程序会美化输出。

```py
init_printing(use_unicode=True)

```

对于某些字符，我们需要启用 unicode 支持。

```py
$ prettify.py
√2
sqrt(2)
------------------------
    2⋅x
ℯ
────
    2
exp(2*x)/2

```

这是输出。 请注意，使用 Jupyter 笔记本会提供更好的输出。

## 平方根

平方根是一个数字，乘以它会产生指定的数量。

`square_root.py`

```py
#!/usr/bin/env python

from sympy import sqrt, pprint, Mul

x = sqrt(2)
y = sqrt(2)

pprint(Mul(x,  y, evaluate=False)) 
print('equals to ')
print(x * y)

```

程序输出一个包含平方根的表达式。

```py
pprint(Mul(x,  y, evaluate=False))

```

我们使用`evaluate`属性推迟对乘法表达式的求值。

```py
$ square_root.py
√2⋅√2
equals to
2

```

这是输出。

## SymPy 符号

符号计算适用于符号，以后可以对其进行求值。 使用符号之前，必须在 SymPy 中定义符号。

`def_sym.py`

```py
#!/usr/bin/env python

# ways to define symbols

from sympy import Symbol, symbols
from sympy.abc import x, y

expr = 2*x + 5*y
print(expr)

a = Symbol('a')
b = Symbol('b')

expr2 = a*b + a - b
print(expr2)

i, j = symbols('i j')
expr3 = 2*i*j + i*j
print(expr3) 

```

该程序显示了三种在 SymPy 中定义符号的方法。

```py
from sympy.abc import x, y

```

可以从`sympy.abc`模块导入符号。 它将所有拉丁字母和希腊字母导出为符号，因此我们可以方便地使用它们。

```py
a = Symbol('a')
b = Symbol('b')

```

可以用`Symbol`定义

```py
i, j = symbols('i j')

```

可以使用`symbols()`方法定义多个符号。

## SymPy 规范表达形式

SymPy 会自动将表达式转换为规范形式。 SymPy 仅执行廉价操作； 因此，表达式可能无法求值为最简单的形式。

`canonical_form.py`

```py
#!/usr/bin/env python

from sympy.abc import a, b

expr = b*a + -4*a + b + a*b + 4*a + (a + b)*3

print(expr)

```

我们有一个带有符号`a`和`b`的表达式。 该表达可以容易地简化。

```py
$ canonical_form.py
2*a*b + 3*a + 4*b

```

这是输出。

## SymPy 扩展代数表达式

使用`expand()`，我们可以扩展代数表达式； 即该方法尝试消除幂和乘法。

`expand.py`

```py
#!/usr/bin/env python

from sympy import expand, pprint
from sympy.abc import x

expr = (x + 1) ** 2

pprint(expr)

print('-----------------------')
print('-----------------------')

expr = expand(expr)
pprint(expr)

```

该程序扩展了一个简单的表达式。

```py
$ expand.py
       2
(x + 1)
-----------------------
-----------------------
 2
x  + 2⋅x + 1

```

这是输出。

## SymPy 简化表达式

可以使用`simplify()`将表达式更改为更简单的形式。

`simplify.py`

```py
#!/usr/bin/env python

from sympy import sin, cos, simplify, pprint
from sympy.abc import x

expr = sin(x) / cos(x)

pprint(expr)

print('-----------------------')

expr = simplify(expr)
pprint(expr)

```

例如将`sin(x)/sin(y)`表达式简化为`tan(x)`。

```py
$ simplify.py
sin(x)
──────
cos(x)
-----------------------
tan(x)

```

这是输出。

## SymPy 比较表达式

SymPy 表达式与`equals()`而不是`==`运算符进行比较。

`expr_equality.py`

```py
#!/usr/bin/env python

from sympy import pprint, Symbol, sin, cos

x = Symbol('x')

a = cos(x)**2 - sin(x)**2
b = cos(2*x)

print(a.equals(b))

# we cannot use == operator
print(a == b)

```

该程序比较两个表达式。

```py
print(a.equals(b))

```

我们用`equals()`比较两个表达式。 在应用该方法之前，SymPy 尝试简化表达式。

```py
$ expr_equality.py
True
False

```

这是输出。

## SymPy 求值表达式

可以通过替换符号来求值表达式。

`evaluating.py`

```py
#!/usr/bin/env python

from sympy import pi

print(pi.evalf(30))

```

该示例将`pi`值求值为 30 个位。

```py
$ evaluating.py
3.14159265358979323846264338328

```

这是输出。

`evaluating2.py`

```py
#!/usr/bin/env python

from sympy.abc import a, b
from sympy import pprint

expr = b*a + -4*a + b + a*b + 4*a + (a + b)*3

print(expr.subs([(a, 3), (b, 2)]))

```

本示例通过用数字替换`a`和`b`符号来求值表达式。

```py
$ evaluating.py
3.14159265358979323846264338328

```

这是输出。

## SymPy 求解方程

用`solve()`或`solveset()`求解方程。

`solving.py`

```py
#!/usr/bin/env python

from sympy import Symbol, solve

x = Symbol('x')

sol = solve(x**2 - x, x)

print(sol)

```

该示例使用`solve()`解决了一个简单方程。

```py
sol = solve(x**2 - x, x)

```

`solve()`的第一个参数是公式。 该公式以适合 SymPy 的特定形式编写； 即`x**2 - x`代替`x**2 = x`。 第二个参数是我们需要解决的符号。

```py
$ solving.py
[0, 1]

```

该方程式有两个解：0 和 1。

或者，我们可以将`Eq`用于公式。

`solving2.py`

```py
#!/usr/bin/env python

from sympy import pprint, Symbol, Eq, solve

x = Symbol('x')

eq1 = Eq(x + 1, 4)
pprint(eq1)

sol = solve(eq1, x)
print(sol)

```

该示例解决了一个简单的`x + 1 = 4`方程。

```py
$ solving2.py
x + 1 = 4
[3]

```

这是输出。

`solving3.py`

```py
#!/usr/bin/env python

from sympy.solvers import solveset
from sympy import Symbol, Interval, pprint

x = Symbol('x')

sol = solveset(x**2 - 1, x, Interval(0, 100))
print(sol)

```

使用`solveset()`，我们找到了给定间隔的解决方案。

```py
$ solving3.py
{1}

```

这是输出。

## SymPy 序列

序列是其中允许重复的对象的枚举集合。 序列可以是有限的或无限的。 元素的数量称为序列的长度。 与集合不同，同一元素可以在序列中的不同位置出现多次。 元素的顺序很重要。

`sequence.py`

```py
#!/usr/bin/env python

from sympy import summation, sequence, pprint
from sympy.abc import x

s = sequence(x, (x, 1, 10))
print(s)
pprint(s)
print(list(s))

print(s.length)

print(summation(s.formula, (x, s.start, s.stop)))
# print(sum(list(s)))

```

本示例创建一个由数字 1、2，...，10 组成的序列。 我们计算这些数字的总和。

```py
$ sequence.py
SeqFormula(x, (x, 1, 10))
[1, 2, 3, 4, …]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
10
55

```

这是输出。

## SymPy 极限

极限是函数（或序列）“接近”作为输入（或索引）“接近”某个值的值。

`limit.py`

```py
#!/usr/bin/env python

from sympy import sin, limit, oo
from sympy.abc import x

l1 = limit(1/x, x, oo)
print(l1)

l2 = limit(1/x, x, 0)
print(l2)

```

在示例中，我们具有`1/x`函数。 它具有左侧和右侧限制。

```py
from sympy import sin, limit, sqrt, oo

```

`oo`表示无穷大。

```py
l1 = limit(1/x, x, oo)
print(l1)

```

我们计算`1/x`的极限，其中`x`接近正无穷大。

```py
$ limit.py
0
oo

```

这是输出。

## SymPy 矩阵

在 SymPy 中，我们可以使用矩阵。 矩阵是数字或其他数学对象的矩形数组，为其定义了运算（例如加法和乘法）。

矩阵用于计算，工程或图像处理。

`matrix.py`

```py
#!/usr/bin/env python

from sympy import Matrix, pprint

M = Matrix([[1, 2], [3, 4], [0, 3]])
print(M)
pprint(M)

N = Matrix([2, 2])

print("---------------------------")
print("M * N")
print("---------------------------")

pprint(M*N)

```

该示例定义了两个矩阵并将它们相乘。

```py
$ matrix.py
Matrix([[1, 2], [3, 4], [0, 3]])
⎡1  2⎤
⎢    ⎥
⎢3  4⎥
⎢    ⎥
⎣0  3⎦
---------------------------
M * N
---------------------------
⎡6 ⎤
⎢  ⎥
⎢14⎥
⎢  ⎥
⎣6 ⎦

```

这是输出。

## SymPy 绘图

SymPy 包含用于绘图的模块。 它基于 Matplotlib 构建。

`simple_plot.py`

```py
#!/usr/bin/env python

# uses matplotlib

import sympy
from sympy.abc import x
from sympy.plotting import plot

plot(1/x)

```

该示例绘制了`1/x`函数的二维图。

这是 SymPy 教程。

您可能也对以下相关教程感兴趣： [PrettyTable 教程](/python/prettytable/)， [Matplotlib 教程](/python/matplotlib/)， [Python 教程](/lang/python/)。