在 Python 裡,有一個套件 SymPy 可以用來做數學符號運算,包括解方程式的根。
若系統尚未安裝 SymPy 這個套件,必須先安裝,例如在 Ubuntu 的終端機裡,可以輸入以下指令安裝:sudo apt install python3-sympy
之後開啟 Spyder,開始使用。
首先我們先匯入需要使用的函式庫:
In [1]: from sympy import solveset, S In [2]: from sympy.abc import x
求一元二次方程式的根
現在可以開始解方程式,例如,求 的根,得到 -1 和 1 兩個根。
In [9]: solveset(x ** 2 - 1, x) Out[9]: FiniteSet(-1, 1)
求 的根:
In [11]: solveset(x ** 2 - x - 6, x) Out[11]: FiniteSet(-2, 3)
求 的根,得到虛數 i 和 –i。
In [12]: solveset(x ** 2 + 1, x) Out[12]: FiniteSet(I, -I)
求 的根:
In [15]: solveset(2 * x ** 2 + 5 * x + 3, x) Out[15]: FiniteSet(-3/2, -1)
求 的根:
In [16]: solveset(x ** 2 + x + 3, x) Out[16]: FiniteSet(-1/2 - sqrt(11)*I/2, -1/2 + sqrt(11)*I/2)
求 的根:
In [17]: solveset(x ** 2 + 5 * x + 3, x) Out[17]: FiniteSet(-5/2 - sqrt(13)/2, -5/2 + sqrt(13)/2)
求一元三次方程式的根
我們也可以解一元三次方程式的根。
例如,分別求以下方程式的根:
In [24]: solveset(x ** 3 - 1, x) Out[24]: FiniteSet(1, -1/2 - sqrt(3)*I/2, -1/2 + sqrt(3)*I/2) In [25]: solveset(x ** 3 + 1, x) Out[25]: FiniteSet(-1, 1/2 - sqrt(3)*I/2, 1/2 + sqrt(3)*I/2) In [26]: solveset(x ** 3 - 2 * x ** 2 + 3 * x - 2, x) Out[26]: FiniteSet(1, 1/2 - sqrt(7)*I/2, 1/2 + sqrt(7)*I/2)
求一元四次方程式的根
我們也可以解更高次的一元方程式的根,例如解以下的一元四次方程式,得到 4 個解。由此可見電腦的威力。
In [28]: solveset(x ** 4 - 2 * x ** 3 + 3 * x ** 2 - 2 * x + 5, x) Out[28]: FiniteSet(1/2 + 73**(1/4)*sin(atan(8/3)/2)/2 - 73**(1/4)*I*cos(atan(8/3)/2)/2, 1/2 + 73**(1/4)*sin(atan(8/3)/2)/2 + 73**(1/4)*I*cos(atan(8/3)/2)/2, -73**(1/4)*sin(atan(8/3)/2)/2 + 1/2 - 73**(1/4)*I*cos(atan(8/3)/2)/2, -73**(1/4)*sin(atan(8/3)/2)/2 + 1/2 + 73**(1/4)*I*cos(atan(8/3)/2)/2)
用數值解表示求出來的根
我們時常需要方程式的數值解,希望計算的結果以浮點數表示。此外,在高次的一元方程式,時常未必會有精確的公式解,這時我們也只能用數值解來表示。在 SymPy 中,提供了方便的數值計算方式,可以用 (expr).evalf()
這個函數,或是用 N(expr)
這 2 種方式。例如:
In [1]: from sympy import * In [2]: from sympy.abc import x In [3]: solveset(x ** 2 + 5 * x + 3, x) Out[3]: FiniteSet(-5/2 - sqrt(13)/2, -5/2 + sqrt(13)/2) In [4]: solveset(x ** 2 + 5 * x + 3, x).evalf() Out[4]: FiniteSet(-4.30277563773199, -0.697224362268005) In [5]: N(solveset(x ** 2 + 5 * x + 3, x)) Out[5]: FiniteSet(-4.30277563773199, -0.697224362268005)
可以用 .evalf(n) 或 N(expr, n) 指定輸出的小數點精確度。
In [6]: solveset(x ** 2 + 5 * x + 3, x).evalf(6) Out[6]: FiniteSet(-4.30278, -0.697224) In [7]: N(solveset(x ** 2 + 5 * x + 3, x), 6) Out[7]: FiniteSet(-4.30278, -0.697224)
帶有虛數的根,也可以表示。如:
In [8]: solveset(x ** 2 + x + 3, x) Out[8]: FiniteSet(-1/2 - sqrt(11)*I/2, -1/2 + sqrt(11)*I/2) In [10]: solveset(x ** 2 + x + 3, x).evalf() Out[10]: FiniteSet(-0.5 - 1.6583123951777*I, -0.5 + 1.6583123951777*I) In [11]: N(solveset(x ** 2 + x + 3, x)) Out[11]: FiniteSet(-0.5 - 1.6583123951777*I, -0.5 + 1.6583123951777*I)
一元五次方以上的方程式,未必會有公式解,這時如果輸入無法計算正確公式解的方程式,系統會傳回 CRootof() 的字樣。此時仍可以計算數值解。例如:
In [18]: solveset(x ** 5 + 9 * x ** 2 - 7, x) Out[18]: FiniteSet(CRootOf(x**5 + 9*x**2 - 7, 0), CRootOf(x**5 + 9*x**2 - 7, 1), CRootOf(x**5 + 9*x**2 - 7, 2), CRootOf(x**5 + 9*x**2 - 7, 3), CRootOf(x**5 + 9*x**2 - 7, 4)) In [19]: solveset(x ** 5 + 9 * x ** 2 - 7, x).evalf() Out[19]: FiniteSet(-1.92255393575455, -0.923195353755875, 0.852996007284856, 0.996376641112782 - 1.90547084829918*I, 0.996376641112782 + 1.90547084829918*I) In [20]: N(solveset(x ** 5 + 9 * x ** 2 - 7, x)) Out[20]: FiniteSet(-1.92255393575455, -0.923195353755875, 0.852996007284856, 0.996376641112782 - 1.90547084829918*I, 0.996376641112782 + 1.90547084829918*I)
設定數學式的輸出格式
在上面的例子,我們看到程式計算出的結果,有時並不容易閱讀,而且可能造成運算符號先後次序的誤解。SymPy 裡提供了其它顯示的設定選項,利用 init_priting()
這個函數,可以讓系統設定較美觀的數學式輸出。
由於 SymPy 數學式的輸出,可以借用一個著名的數學排版軟體 的格式,所以建議先在系統內安裝 。在 Ubuntu 下,可以在終端機下輸入以下指令安裝:sudo apt install texlive
回到 Spyder,要輸出較好看的數學式,可以先啟用 init_printing():
In [3]: from sympy import init_printing In [4]: init_printing()
之後,我們再依這篇文章前述方法,來計算方程式的根,會發現輸出的格式不同了。輸出的結果會轉換成較類似數學常用格式的圖檔顯示。
In [5]: solveset(x ** 2 + x + 3, x) Out[5]: In [6]: solveset(x ** 2 + 5 * x + 3, x) Out[6]: In [7]: solveset(x ** 3 - 1, x) Out[7]:
在此呈現 IPython console 的畫面截圖,把以下圖檔點開放大欣賞,我們看到前述一元四次方程式的解,寫成數學式後,較清楚明瞭了。
參考閱讀:
https://docs.sympy.org/latest/modules/solvers/solveset.html#module-sympy.solvers.solveset
你必須登入才能發表留言。