鱼C论坛

 找回密码
 立即注册
查看: 3376|回复: 3

[技术交流] sympy讲解

[复制链接]
发表于 2019-5-27 17:51:58 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 TCY 于 2021-2-14 13:48 编辑

sympy是一个Python的科学计算库,用一套强大的符号计算体系完成诸如多项式求值、求极限、解方程、求积分、微分方程、级数展开、矩阵运算等等计算问题。虽然Matlab的类似科学计算能力也很强大,但是Python以其语法简单、易上手、异常丰富的三方库生态,个人认为可以更优雅地解决日常遇到的各种计算问题。
如果你遇到了一个难题,不要犹豫,来找Python,它几乎不会让你失望的。

安装sympy库
  1. pip install sympy
复制代码

常用的sympy内置符号
虚数单位i
  1. In [13]: import sympy

  2. In [14]: sympy.I
  3. Out[14]: I

  4. In [15]: sympy.I ** 2
  5. Out[15]: -1

  6. # 求-1的平方根
  7. In [16]: sympy.sqrt(-1)
  8. Out[16]: I
复制代码

注:本文后面的示例都省略导包语句:import sympy
自然对数的底e
  1. In [18]: sympy.E
  2. Out[18]: E

  3. # 求对数
  4. In [20]: sympy.log(sympy.E)
  5. Out[20]: 1
复制代码

无穷大oo
  1. In [26]: 1 / sympy.oo
  2. Out[26]: 0

  3. In [27]: 1 + sympy.oo
  4. Out[27]: oo
复制代码

圆周率pi
  1. In [60]: sympy.pi
  2. Out[60]: pi

  3. In [61]: sympy.sin(sympy.pi / 2)
  4. Out[61]: 1
复制代码

用sympy进行初等运算
Python 2.x中用除号/做两个整数的除法,实际上是整除运算,为了防止这种情况的发生,避免不必要的麻烦,下文的所有示例一开始都加上一句:from __future__ import division,这个时候除号/本身就变成了真实除法,而//才是整除,比如:
  1. # 导入division包之前
  2. In [1]: 1/2
  3. Out[1]: 0

  4. In [2]: from __future__ import division

  5. # 导入division包之后
  6. In [3]: 1/2
  7. Out[3]: 0.5

  8. In [4]: 1//2
  9. Out[4]: 0
复制代码

求对数
  1. # 自然对数
  2. In [10]: sympy.log(sympy.E)
  3. Out[10]: 1

  4. In [11]: sympy.log(sympy.E ** 3)
  5. Out[11]: 3

  6. # 以10为底1000的对数
  7. In [12]: sympy.log(1000,10)
  8. Out[12]: 3
复制代码

求平方根
  1. In [13]: sympy.sqrt(4)
  2. Out[13]: 2

  3. In [14]: sympy.sqrt(-1)
  4. Out[14]: I
复制代码

求n次方根
  1. # 求8的3次方根
  2. In [15]: sympy.root(8,3)
  3. Out[15]: 2
复制代码

求k次方
  1. In [21]: 2 ** 3
  2. Out[21]: 8

  3. In [22]: 16 ** (1 / 2)
  4. Out[22]: 4.0
复制代码

求阶乘
  1. In [35]:  sympy.factorial(4)
  2. Out[35]: 24
复制代码

求三角函数
sin函数为例:
  1. In [86]: sympy.sin(sympy.pi)
  2. Out[86]: 0

  3. In [87]: sympy.sin(sympy.pi / 2)
  4. Out[87]: 1
复制代码

表达式与表达式求值
sympy可以用一套符号系统来表示一个表达式,如函数、多项式等,并且可以进行求值,比如:
  1. # 首先定义x为一个符号,表示一个变量
  2. In [96]: x = sympy.Symbol('x')

  3. In [97]: fx = 2 * x + 1

  4. # 可以看到fx是一个sympy.core.add.Add类型的对象,也就是一个表达式
  5. In [98]: type(fx)
  6. Out[98]: sympy.core.add.Add

  7. # 用evalf函数,传入变量的值,对表达式进行求值
  8. In [101]: fx.evalf(subs = {x : 2})
  9. Out[101]: 5.00000000000000
复制代码
还支持多元表达式:
  1. In [102]: x,y = sympy.symbols('x y')

  2. In [103]: f = 2 * x + y

  3. # 以字典的形式传入多个变量的值
  4. In [104]: f.evalf(subs = {x : 1, y : 2})
  5. Out[104]: 4.00000000000000

  6. # 如果只传入一个变量的值,则原本输出原来的表达式
  7. In [105]: f.evalf(subs = {x : 1})
  8. Out[105]: 2.0*x + y
复制代码

用sympy解方程(组)

使用sympy.solve函数解方程,该函数通常传入两个参数,第1个参数是方程的表达式(把方程所有的项移到等号的同一边形成的式子),第2个参数是方程中的未知数。函数的返回值是一个列表,代表方程的所有根(可能为复数根)。
解最简单的方程
比如下面我们来求两个方程:
  1. # 首先定义‘x’为一个符号,代表一个未知数
  2. In [24]: x = sympy.Symbol('x')

  3. # 解方程:x - 1 = 0
  4. In [25]: sympy.solve(x - 1, x)
  5. Out[25]: [1]

  6. # 解方程:x ^ 2 - 1 = 0
  7. In [26]: sympy.solve(x ** 2 - 1, x)
  8. Out[26]: [-1, 1]

  9. # 解方程:x ^ 2 + 1 = 0
  10. In [27]: sympy.solve(x ** 2 + 1, x)
  11. Out[27]: [-I, I]
复制代码

把函数式赋给一个变量

有时候为了书写起来简洁,可以把一个函数式起个名字,比如:
  1. In [30]: x = sympy.Symbol('x')

  2. In [31]: f = x + 1

  3. In [32]: sympy.solve(f, x)
复制代码

解方程组

比如要解这么个二元一次方程组:
8819542-72c7beb45226ccf9.png
代码如下:
  1. # 一次性定义多个符号
  2. In [28]: x,y = sympy.symbols('x y')

  3. In [29]: sympy.solve([x + y - 1,x - y -3], [x, y])
  4. Out[29]: {x: 2, y: -1}
复制代码

计算求和式
计算求和式可以使用sympy.summation函数,其函数原型为:sympy.summation(f, *symbols, **kwargs)
话不多少,举个栗子,比如求下面这个求和式子的值:
8819542-e779aa77893798bd.png
我们用初中的知识可以知道,这个式子的结果为:5050 * 2 = 10100
下面用代码来求:
  1. In [37]: n = sympy.Symbol('n')

  2. In [38]: sympy.summation(2 * n, (n, 1, 100))
  3. Out[38]: 10100
复制代码
可见结果是正确的。
如果sympy.summation函数无法计算出具体的结果,那么会返回求和表达式。

解带有求和式的方程
比如求这么一个方程:
8819542-b7b391f37657a927.png
代码如下:
  1. In [43]: x = sympy.Symbol('x')

  2. In [44]: i = sympy.Symbol('i', integer = True)

  3. In [46]: f =  sympy.summation(x, (i, 1, 5)) + 10 * x - 15

  4. In [47]: sympy.solve(f, x)
  5. Out[47]: [1]
复制代码


求极限

求极限用sympy.limit函数,其函数文档如下:
  1. Signature: sympy.limit(e, z, z0, dir='+')
  2. Docstring:
  3. Compute the limit of e(z) at the point z0.

  4. z0 can be any expression, including oo and -oo.

  5. For dir="+" (default) it calculates the limit from the right
  6. (z->z0+) and for dir="-" the limit from the left (z->z0-).  For infinite
  7. z0 (oo or -oo), the dir argument is determined from the direction
  8. of the infinity (i.e., dir="-" for oo).
复制代码
函数文档中已经说得很清楚了,下面用代码示例来求几个极限。

如果学过微积分,就会知道微积分中有3个重要的极限:
8819542-184b70faf3c1275b.png
8819542-ee5d3990a0dc59ae.png
8819542-feb0fef92aa4cd0b.png
下面就用sympy.limit函数来分别求这3个极限:
  1. In [53]: x = sympy.Symbol('x')

  2. In [54]: f1 = sympy.sin(x)/x

  3. In [55]: sympy.limit(f1,x,0)
  4. Out[55]: 1

  5. In [56]: f2 = (1+x)**(1/x)

  6. In [57]: sympy.limit(f2,x,0)
  7. Out[57]: E

  8. In [58]: f3 = (1+1/x)**x

  9. In [59]: sympy.limit(f3,x,sympy.oo)
  10. Out[59]: E
复制代码
可见三个极限的计算结果都完全正确。

求导
求导使用sympy.diff函数,传入2个参数:函数表达式和变量名,举例如下:
  1. In [63]: x = sympy.Symbol('x')

  2. In [64]: f = x ** 2 + 2 * x + 1

  3. In [65]: sympy.diff(f, x)
  4. Out[65]: 2*x + 2

  5. In [66]: f2 = sympy.sin(x)

  6. In [67]: sympy.diff(f2, x)
  7. Out[67]: cos(x)

  8. # 多元函数求偏导
  9. In [68]: y = sympy.Symbol('y')

  10. In [70]: f3 = x ** 2 + 2*x + y ** 3

  11. In [71]: sympy.diff(f3, x)
  12. Out[71]: 2*x + 2

  13. In [72]: sympy.diff(f3, y)
  14. Out[72]: 3 * y ** 2
复制代码

求定积分
使用sympy.integrate函数求定积分,其功能比较复杂,非常强大,下面仅仅举几个比较简单的例子。
先来求一个最简单的积分:
8819542-aabc41f9bfe28f1d.png
牛顿-莱布尼兹公式可以立马口算出上面这个式子的结果是1,用代码计算如下:
  1. In [74]: x = sympy.Symbol('x')

  2. In [75]: f = 2 * x

  3. # 传入函数表达式和积分变量、积分下限、上限
  4. In [76]: sympy.integrate(f,(x,0,1))
  5. Out[76]: 1
复制代码

下面来算一个复杂一点的多重积分:
8819542-fed1bbd18cde1427.png
其中:
8819542-7de76f6e53c71ec7.png
我们通过口算可以求出f(x)
8819542-95c54a9c5647a7ca.png
所以:
8819542-77ea58537b677f66.png
下面用代码来计算上述过程:
  1. In [82]: t,x = sympy.symbols('t x')

  2. In [83]: f = 2 * t

  3. In [84]: g = sympy.integrate(f,(t,0,x))

  4. In [85]: sympy.integrate(g,(x,0,3))
  5. Out[85]: 9
复制代码

求不定积分
同样也是使用sympy.integrate函数求不定积分,下面仅仅举几个比较简单的例子。
比如求下面这个不定积分:
8819542-cd7eb2ff2d91a49e.png
通过观察我们知道它的结果是:
8819542-b1268da5b014caed.png
下面用代码来计算这个不定积分的结果:
  1. In [79]: x = sympy.Symbol('x')

  2. In [80]: f = sympy.E ** x + 2 * x

  3. In [81]: sympy.integrate(f,x)
  4. Out[81]: x**2 + exp(x)
复制代码

总结

从上面的一系列计算可以看出,sympy是个非常强大的科学计算库,本文所讲到的用法仅仅是它强大功能的冰山一角,还需以后在实际使用中进一步发掘。

作者:m2fox
链接:https://www.jianshu.com/p/339c91ae9f41
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。




小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2019-5-27 17:53:59 From FishC Mobile | 显示全部楼层
太专业了,一般人用不着
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-7-27 21:31:48 | 显示全部楼层
专业
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2021-5-11 22:53:23 | 显示全部楼层
本人没文化,只知道牛。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-6-24 01:20

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表