Python 解方程的三種方法

# 首發於我的博客 The North.

新年第一篇,搞起.

這回寫一個好久之前想做,一直擱著沒做的東西—— Python 解方程(其實是放假回家,趁著家裡電腦重裝 LOL 的時間過來寫一篇). 咱這回用三種不同的方法,來應對平常碰到的簡單方程.

Numpy 求解線性方程組

例如我們要解一個這樣的二元一次方程組:

x + 2y = 3n4x + 5y = 6n

當然我們可以手動寫出解析解,然後寫一個函數來求解,這實際上只是用 Python 來單純做「數值計算」. 但實際上,numpy.linalg.solve 可以直接求解線性方程組.

一般地,我們設解線性方程組形如 Ax=b,其中 A 是係數矩陣,b 是一維(n 維也可以,這個下面會提到),x 是未知變數. 再拿上面地最簡單的二元一次方程組為例,我們用 numpy.linalg.solve 可以這樣寫:

In [1]: import numpy as npn ...: A = np.mat(1,2; 4,5) # 構造係數矩陣 An ...: b = np.mat(3,6).T # 構造轉置矩陣 b (這裡必須為列向量)n ...: r = np.linalg.solve(A,b) # 調用 solve 函數求解n ...: print rn ...:nOut[1]: [[-1.]n [ 2.]]n

那麼前面提到的「 n 維」情形是什麼呢?實際上就是同時求解多組形式相同的二元一次方程組,例如我們想同時求解這樣兩組:

x + 2y = 3n4x + 5y = 6n

x + 2y = 7n4x + 5y = 8n

就可以這樣寫:

In [2]: import numpy as npn ...: A = np.mat(1,2; 4,5) # 構造係數矩陣 An ...: b = np.array([[3,6], [7,8]]).T # 構造轉置矩陣 b (這裡必須為列向量),n ...: 注意這裡用的是 arrayn ...: r = np.linalg.solve(A,b) # 調用 solve 函數求解n ...: print rn ...:nOut[2]: [[-1. -6.33333333]n [ 2. 6.66666667]]n

SciPy 求解非線性方程組

先看官方文檔的介紹:

scipy.optimize.fsolve(func, x0, args=(), fprime=None, full_output=0, col_deriv=0, xtol=1.49012e-08, maxfev=0, band=None, epsfcn=None, factor=100, diag=None)[source]n

一般來說,我們只需要用到 func 和 x0 就夠了. func 是自己構造的函數,也就是需要求解的方程組的左端(右端為 0),而 x0 則是給定的初值.

我們來看一個具體的例子,求解:

x + 2y + 3z - 6 = 0n5 * (x ** 2) + 6 * (y ** 2) + 7 * (z ** 2) - 18 = 0n9 * (x ** 3) + 10 * (y ** 3) + 11 * (z ** 3) - 30 = 0n

就可以這麼寫:

In [3]: from scipy.optimize import fsolven ...:n ...: def func(i):n ...: x, y, z = i[0], i[1], i[2]n ...: return [n ...: x + 2 * y + 3 * z - 6,n ...: 5 * (x ** 2) + 6 * (y ** 2) + 7 * (z ** 2) - 18,n ...: 9 * (x ** 3) + 10 * (y ** 3) + 11 * (z ** 3) - 30n ...: ]n ...:n ...: r = fsolve(func,[0, 0, 0])n ...: print rn ...:nOut[3]: [ 1.00000001 0.99999998 1.00000001]n

當然,SciPy 也可以用來求解線性方程組,這是因為 scipy.optimize.fsolve 本質上是最小二乘法來逼近真實結果.

SymPy 通吃一切

例如求解一個:

x + 2 * (x ** 2) + 3 * (x ** 3) - 6 = 0n

直接就是:

In [4]: from sympy import *n ...: x = symbols(x)n ...: solve(x + 2 * (x ** 2) + 3 * (x ** 3) - 6, x)nOut[4]: [1, -5/6 - sqrt(47)*I/6, -5/6 + sqrt(47)*I/6]n

另外,@Wayne Shi 的這篇 使用 Python 解數學方程 ,就重點講述了 SymPy 解線性方程組的方法,所以我也就不再贅述了。

其實 SymPy 能幹的太多了,有興趣的可以看一看 GitHub上的 Quick examples.

最後

安利自己一波,求一份關於 程序化投資 方向的寒假實習.

這是我的簡歷,歡迎騷擾.


推薦閱讀:

python中的時間處理大總結
極光日報 第 163 期 | 2017 / 4 / 24
Python從零開始系列連載(1)——安裝環境
Python黑帽編程1.1虛擬機安裝和配置 Kali Linux 2016
20170403Python控制流if、while、for語句學習

TAG:Python | 数学 | 方程 |