Python科學(xué)計(jì)算利器——SymPy庫

本文講述的核心庫:sympy
官方在線文檔:http://docs.sympy.org/0.7.1/guide.html#guide

sympy是一個(gè)Python的科學(xué)計(jì)算庫,用一套強(qiáng)大的符號(hào)計(jì)算體系完成諸如多項(xiàng)式求值、求極限、解方程、求積分、微分方程、級(jí)數(shù)展開、矩陣運(yùn)算等等計(jì)算問題。雖然Matlab的類似科學(xué)計(jì)算能力也很強(qiáng)大,但是Python以其語法簡(jiǎn)單、易上手、異常豐富的三方庫生態(tài),個(gè)人認(rèn)為可以更優(yōu)雅地解決日常遇到的各種計(jì)算問題。

如果你遇到了一個(gè)難題,不要猶豫,來找Python,它幾乎不會(huì)讓你失望的。寫本文的初衷也是妹子在做金融作業(yè)的時(shí)候遇到大量的計(jì)算,用普通計(jì)算器算真是工程量浩大,所以找到sympy這么個(gè)庫,寫代碼幫忙輔助計(jì)算一下,然后在這里寫博客記錄下來。

安裝sympy庫

pip install sympy

常用的sympy內(nèi)置符號(hào)

虛數(shù)單位i

In [13]: import sympy

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

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

# 求-1的平方根
In [16]: sympy.sqrt(-1)
Out[16]: I

注:本文后面的示例都省略導(dǎo)包語句:import sympy

自然對(duì)數(shù)的底e

In [18]: sympy.E
Out[18]: E

# 求對(duì)數(shù)
In [20]: sympy.log(sympy.E)
Out[20]: 1

無窮大oo

In [26]: 1/sympy.oo
Out[26]: 0

In [27]: 1 + sympy.oo
Out[27]: oo

圓周率pi

In [60]: sympy.pi
Out[60]: pi

In [61]: sympy.sin(sympy.pi/2)
Out[61]: 1

用sympy進(jìn)行初等運(yùn)算

Python 2.x中用除號(hào)/做兩個(gè)整數(shù)的除法,實(shí)際上是整除運(yùn)算,為了防止這種情況的發(fā)生,避免不必要的麻煩,下文的所有示例一開始都加上一句:from __future__ import division,這個(gè)時(shí)候除號(hào)/本身就變成了真實(shí)除法,而//才是整除,比如:

# 導(dǎo)入division包之前
In [1]: 1/2
Out[1]: 0

In [2]: from __future__ import division

# 導(dǎo)入division包之后
In [3]: 1/2
Out[3]: 0.5

In [4]: 1//2
Out[4]: 0

求對(duì)數(shù)

# 自然對(duì)數(shù)
In [10]: sympy.log(sympy.E)
Out[10]: 1

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

# 以10為底1000的對(duì)數(shù)
In [12]: sympy.log(1000,10)
Out[12]: 3

求平方根

In [13]: sympy.sqrt(4)
Out[13]: 2

In [14]: sympy.sqrt(-1)
Out[14]: I

求n次方根

# 求8的3次方根
In [15]: sympy.root(8,3)
Out[15]: 2

求k次方

In [21]: 2 ** 3
Out[21]: 8

In [22]: 16 ** (1/2)
Out[22]: 4.0

求階乘

In [35]:  sympy.factorial(4)
Out[35]: 24

求三角函數(shù)

sin函數(shù)為例:

In [86]: sympy.sin(sympy.pi)
Out[86]: 0

In [87]: sympy.sin(sympy.pi/2)
Out[87]: 1

表達(dá)式與表達(dá)式求值

sympy可以用一套符號(hào)系統(tǒng)來表示一個(gè)表達(dá)式,如函數(shù)、多項(xiàng)式等,并且可以進(jìn)行求值,比如:

# 首先定義x為一個(gè)符號(hào),表示一個(gè)變量
In [96]: x = sympy.Symbol('x')

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

# 可以看到fx是一個(gè)sympy.core.add.Add類型的對(duì)象,也就是一個(gè)表達(dá)式
In [98]: type(fx)
Out[98]: sympy.core.add.Add

# 用evalf函數(shù),傳入變量的值,對(duì)表達(dá)式進(jìn)行求值
In [101]: fx.evalf(subs={x:2})
Out[101]: 5.00000000000000

還支持多元表達(dá)式:

In [102]: x,y = sympy.symbols('x y')

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

# 以字典的形式傳入多個(gè)變量的值
In [104]: f.evalf(subs = {x:1,y:2})
Out[104]: 4.00000000000000

# 如果只傳入一個(gè)變量的值,則原本輸出原來的表達(dá)式
In [105]: f.evalf(subs = {x:1})
Out[105]: 2.0*x + y

用sympy解方程(組)

使用sympy.solve函數(shù)解方程,該函數(shù)通常傳入兩個(gè)參數(shù),第1個(gè)參數(shù)是方程的表達(dá)式(把方程所有的項(xiàng)移到等號(hào)的同一邊形成的式子),第2個(gè)參數(shù)是方程中的未知數(shù)。函數(shù)的返回值是一個(gè)列表,代表方程的所有根(可能為復(fù)數(shù)根)。

解最簡(jiǎn)單的方程

比如下面我們來求兩個(gè)方程:

# 首先定義 `x`為一個(gè)符號(hào),代表一個(gè)未知數(shù)
In [24]: x = sympy.Symbol('x')

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

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

# 解方程:x ^ 2 + 1 = 0
In [27]: sympy.solve(x ** 2 + 1,x)
Out[27]: [-I, I]

把函數(shù)式賦給一個(gè)變量

有時(shí)候?yàn)榱藭鴮懫饋砗?jiǎn)潔,可以把一個(gè)函數(shù)式起個(gè)名字,比如:

In [30]: x = sympy.Symbol('x')

In [31]: f = x + 1

In [32]: sympy.solve(f,x)
Out[32]: [-1]

解方程組

比如要解這么個(gè)二元一次方程組:


代碼如下:

# 一次性定義多個(gè)符號(hào)
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}

計(jì)算求和式

計(jì)算求和式可以使用sympy.summation函數(shù),其函數(shù)原型為:sympy.summation(f, *symbols, **kwargs)

話不多少,舉個(gè)栗子,比如求下面這個(gè)求和式子的值:


我們用初中的知識(shí)可以知道,這個(gè)式子的結(jié)果為:5050 * 2 = 10100

下面用代碼來求:

In [37]: n = sympy.Symbol('n')

In [38]: sympy.summation(2 * n,(n,1,100))
Out[38]: 10100

可見結(jié)果是正確的。

如果sympy.summation函數(shù)無法計(jì)算出具體的結(jié)果,那么會(huì)返回求和表達(dá)式。

解帶有求和式的方程

比如求這么一個(gè)方程:


代碼如下:

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]

求極限

求極限用sympy.limit函數(shù),其函數(shù)文檔如下:

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).

函數(shù)文檔中已經(jīng)說得很清楚了,下面用代碼示例來求幾個(gè)極限。

如果學(xué)過微積分,就會(huì)知道微積分中有3個(gè)重要的極限:




下面就用sympy.limit函數(shù)來分別求這3個(gè)極限:

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

可見三個(gè)極限的計(jì)算結(jié)果都完全正確。

求導(dǎo)

求導(dǎo)使用sympy.diff函數(shù),傳入2個(gè)參數(shù):函數(shù)表達(dá)式和變量名,舉例如下:

In [63]: x = sympy.Symbol('x')

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

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

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

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

# 多元函數(shù)求偏導(dǎo)
In [68]: y = sympy.Symbol('y')

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

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

In [72]: sympy.diff(f3,y)
Out[72]: 3*y**2

求定積分

使用sympy.integrate函數(shù)求定積分,其功能比較復(fù)雜,非常強(qiáng)大,下面僅僅舉幾個(gè)比較簡(jiǎn)單的例子。

先來求一個(gè)最簡(jiǎn)單的積分:


牛頓-萊布尼茲公式可以立馬口算出上面這個(gè)式子的結(jié)果是1,用代碼計(jì)算如下:

n [74]: x = sympy.Symbol('x')

n [75]: f = 2 * x

# 傳入函數(shù)表達(dá)式和積分變量、積分下限、上限
n [76]: sympy.integrate(f,(x,0,1))
ut[76]: 1

下面來算一個(gè)復(fù)雜一點(diǎn)的多重積分:



其中:


我們通過口算可以求出f(x)

所以:


下面用代碼來計(jì)算上述過程:

In [82]: t,x = sympy.symbols('t x')

In [83]: f = 2 * t

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

In [85]: sympy.integrate(g,(x,0,3))
Out[85]: 9

求不定積分

同樣也是使用sympy.integrate函數(shù)求不定積分,下面僅僅舉幾個(gè)比較簡(jiǎn)單的例子。

比如求下面這個(gè)不定積分:


通過觀察我們知道它的結(jié)果是:


下面用代碼來計(jì)算這個(gè)不定積分的結(jié)果:

In [79]: x = sympy.Symbol('x')

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

In [81]: sympy.integrate(f,x)
Out[81]: x**2 + exp(x)

總結(jié)

從上面的一系列計(jì)算可以看出,sympy是個(gè)非常強(qiáng)大的科學(xué)計(jì)算庫,本文所講到的用法僅僅是它強(qiáng)大功能的冰山一角,還需以后在實(shí)際使用中進(jìn)一步發(fā)掘。

本文所有較為復(fù)雜的數(shù)學(xué)公式都是先在MS Word的公式編輯器中編輯完之后截圖到這里的。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,068評(píng)論 25 709
  • 作品:羅馬記憶房間思維導(dǎo)圖 作者:李梓琦 日期:2017年5月13日 謝謝你...
    娜琦琦閱讀 374評(píng)論 2 4
  • 時(shí)間到了, 一切的努力, 變戲法似的, 成為一個(gè)謎……
    小劇在成長(zhǎng)閱讀 216評(píng)論 0 2
  • 有一種諾言 是首獨(dú)奏的舞曲 像灑了鹽的蜜糖 永遠(yuǎn)沾不上 心靈的味蕾 有一種謊言 像把無骨的陽傘 永遠(yuǎn)撐不開 被遺棄...
    秋鳶子閱讀 279評(píng)論 0 1

友情鏈接更多精彩內(nèi)容