官网sympy库文档地址:docs.sympy.org/
sympy库是什么:
sympy是一个Python的科学计算库,用一套强大的符号计算体系完成诸如多项式求值、求极限、解方程、求积分、微分方程、级数展开、矩阵运算等计算问题。虽然Matlab的类似科学计算能力也很强大,但是Python以其语法简单、易上手、异常丰富的三方库生态,使其可以更优雅地解决日常遇到的各种计算问题。
前言:写这篇文档的目的是数学建模竞赛使用python编程软件来制作,而牵扯到了数学,则学习sympy库则是必不可缺的,所以便查阅资料写下此篇文章方便一起比赛的同学参考学习。
安装sympy库的流程我在此便不再赘述,下面直接进入正题。
使用代码表示数学符号与手写体的数学运算符号存在一定的差异,下面列举常用的运算符:
- 加号 +
- 减号 -
- 除号 /
- 乘号 *
- 指数 **
- 对数 log()
- e的指数次幂 exp()
- 虚数I
- 无穷大oo
- 圆周率pi
求虚数单位i:
In [1]: import sympy
In [2]: sympy.I
Out[2]: I
In [3]: sympy.I ** 2
Out[3]: -1
# 求-1的平方根
In [4]: sympy.sqrt(-1)
Out[4]: I
求自然对数的底e:
In [5]: sympy.E
Out[5]: E
# 求对数
In [6]: sympy.log(sympy.E)
Out[6]: 1
求无穷大oo:
In [7]: 1/sympy.oo
Out[7]: 0
In [8]: 1 + sympy.oo
Out[8]: oo
求圆周率pi相关:
In [9]: sympy.pi
Out[9]: pi
#求sin(π/2)
In [10]: sympy.sin(sympy.pi/2)
Out[10]: 1
求对数:
# 自然对数
In [1]: sympy.log(sympy.E)
Out[1]: 1
In [2]: sympy.log(sympy.E ** 3)
Out[2]: 3
# 以10为底10000的对数
In [3]: sympy.log(10000,10)
Out[3]: 4
求n次方根:
# 求8的3次方根
In [15]: sympy.root(8,3)
Out[15]: 2
注释:平方根用sqrt和root都可以
求k次方:
In [1]: 2 ** 3
Out[1]: 8
In [2]: 16 ** (1/2)
Out[2]: 4.0
求阶乘:
In [3]: sympy.factorial(4)
Out[3]: 24
求三角函数:
In [6]: sympy.sin(sympy.pi)
Out[6]: 0
In [7]: sympy.sin(sympy.pi/2)
Out[7]: 1
In [8]: sympy.cos(sympy.pi/2)
Out[8]: 0
简单介绍下上述使用方法,接下来解决实际问题:
表达式与表达式求值:
sympy可以用一套符号系统来表示一个表达式,如函数、多项式等,并且可以进行求值,例如:
# 首先定义x为一个符号,表示一个变量
In [1]: x = sympy.Symbol('x')
In [2]: fx = 2*x + 1
# 可以看到fx是一个sympy.core.add.Add类型的对象,也就是一个表达式(type表示类型)
In [3]: type(fx)
Out[3]: sympy.core.add.Add
# 用evalf函数,传入变量的值,对表达式进行求值
In [4]: fx.evalf(subs={x:2})
Out[4]: 5.00000000000000
此处是evalf函数并非eval函数
evalf()函数可以用求出表达式的浮点数。
例:
In [3]:from sympy import *
In [4]:a=Symbol('a')
In [5]:(1/a).evalf(subs={a:3.0} ,n=21)
Out[5]:0.333333333333333333333
由此我们可以看出n=21表示保留小数点后21位
注释:eval() 函数用来执行一个字符串表达式,并返回表达式的值。
语法:eval(expression[, globals[, locals]])
参数:
expression -- 表达式。
globals -- 变量作用域,全局命名空间,如果被提供,则必须是一个字典对象。
locals -- 变量作用域,局部命名空间,如果被提供,可以是任何映射对象。
支持多元表达式表达:
In [2]: x,y = sympy.symbols('x y')
In [3]: f = 2 * x + y
# 以字典的形式传入多个变量的值(注意此处为字典键值对形式)
In [4]: f.evalf(subs = {x:1,y:2})
Out[4]: 4.00000000000000
# 如果只传入一个变量的值,则原本输出原来的表达式
In [5]: f.evalf(subs = {x:1})
Out[5]: 2.0*x + y
解方程(组):
使用sympy.solve
函数解方程,该函数通常传入两个参数,第1个参数是方程的表达式(把方程所有的项移到等号的同一边形成的式子),第2个参数是方程中的未知数。函数的返回值是一个列表,代表方程的所有根(可能为复数根),
形式为:solve(f, symbols, flags)
例:解个简单方程
# 首先定义 `x`为一个符号,代表一个未知数
In [1]: x = sympy.Symbol('x')
# 解方程:x - 1 = 0
In [2]: sympy.solve(x - 1,x)
Out[2]: [1]
# 解方程:x ^ 2 - 1 = 0
In [3]: sympy.solve(x ** 2 - 1,x)
Out[3]: [-1, 1]
# 解方程:x ^ 2 + 1 = 0
In [4]: sympy.solve(x ** 2 + 1,x)
Out[4]: [-I, I]
例:解方程组:
# 一次性定义多个符号
In [28]: x,y = sympy.symbols('x y')
In [29]: sympy.solve([x + y - 1,x - y -3],[x,y])
Out[29]: {x: 2, y: -1}
此时我想你们已经发现了:定义一个未知数符号用的Symbol,而定义多个则用symbols,注意大小写。
计算求和式:
计算求和式可以使用sympy.summation函数,其函数原型为:
sympy.summation(f, *symbols, **kwargs)。
在Python中的代码中经常会见到这两个词 args 和 kwargs,前面通常还会加上一个或者两个星号。
别被这些语句所绊倒。其实这些并不是什么超级特殊的参数,也并不奇特,只是编程人员约定的变量名字,args 是 arguments 的缩写,表示位置参数;kwargs 是 keyword arguments 的缩写,表示关键字参数。
这其实就是 Python 中可变参数的两种形式,并且 *args 必须放在 **kwargs 的前面,因为位置参数在关键字参数的前面。
话不多少,举个栗子,比如求下面这个求和式子的值:
In [37]: n = sympy.Symbol('n')
In [38]: sympy.summation(3 * n,(n,1,100))
Out[38]: 15150
是不是很方便呢哈哈哈哈
如果sympy.summation函数无法计算出具体的结果,那么会返回求和表达式。
解带有求和式的方程:
In [43]: x = sympy.Symbol('x')
In [44]: i = sympy.Symbol('i',integer = True)
In [46]: f = sympy.summation(x,(i,1,5)) + 10 * x - 15
In [47]: sympy.solve(f,x)
Out[47]: [1]
注释:integer--整数,是numeric的一部分
求极限
求极限用sympy.limit
函数,官方文档如下:
Signature: sympy.limit(e, z, z0, dir='+')
Docstring:
Compute the limit of e(z) at the point z0.
z0 can be any expression, including oo and -oo.
For dir="+" (default) it calculates the limit from the right
(z->z0+) and for dir="-" the limit from the left (z->z0-). For infinite
z0 (oo or -oo), the dir argument is determined from the direction
of the infinity (i.e., dir="-" for oo).
下面给出3个例子求微积分的极限:
In [53]: x = sympy.Symbol('x')
In [54]: f1 = sympy.sin(x)/x
In [55]: sympy.limit(f1,x,0)
Out[55]: 1
In [56]: f2 = (1+x)**(1/x)
In [57]: sympy.limit(f2,x,0)
Out[57]: E
In [58]: f3 = (1+1/x)**x
In [59]: sympy.limit(f3,x,sympy.oo)
Out[59]: E
第一个参数表示表达式,第二个参数表示需要求的未知量x(即变量名x),第二个参数表示x趋于的值
求导:
求导使用sympy.diff
函数,传入2个参数:函数表达式和变量名,举例:
In [1]: x = sympy.Symbol('x')
In [2]: f = x ** 2 + 2 * x + 1
In [3]: sympy.diff(f,x)
Out[3]: 2*x + 2
In [4]: f2 = sympy.sin(x)
In [6]: sympy.diff(f2,x)
Out[6]: cos(x)
# 多元函数求偏导
In [1]: y = sympy.Symbol('y')
In [2]: f3 = x**2 + 2*x + y**3
In [3]: sympy.diff(f3,x)
Out[3]: 2*x + 2
In [4]: sympy.diff(f3,y)
Out[4]: 3*y**2
求定积分:
使用sympy.integrate
函数求定积分,其功能比较复杂,非常强大,下面仅举几个比较简单的例子:
In [74]: x = sympy.Symbol('x')
In [75]: f = 2 * x
# 传入函数表达式和积分变量、积分下限、上限
In [76]: sympy.integrate(f,(x,0,1))
Out[76]: 1
牛顿-莱布尼兹公式
下面来算一个复杂一点的多重积分:
其中:
我们通过口算可以求出f(x):
所以:
下面用代码来实现上述过程:
In [82]: t,x = sympy.symbols('t x')
In [83]: f = 2 * t
#此处换元法引入t
In [84]: g = sympy.integrate(f,(t,0,x))
In [85]: sympy.integrate(g,(x,0,3))
Out[85]: 9
求不定积分:
同样也是使用sympy.integrate
函数求不定积分
我们知道它的结果是:
用代码来计算这个不定积分的结果:
In [1]: x = sympy.Symbol('x')
In [2]: f = sympy.E ** x + 2 * x
In [3]: sympy.integrate(f,x)
Out[3]: x**2 + exp(x)
注: exp(x)表示e的x方
本文只是简单介绍了下sympy库的初步使用以及初步涉及高数,更多算法功能等我继续挖掘学习后再来探讨。