第 3 章 一元方程與聯立方程¶
本章重點:
- 了解「方程」的觀念與解的意義。
- 使用 SymPy 解一元一次、二次以及一般非線性方程。
- 使用 SymPy 解二元、三元聯立一次方程組。
- 認識參數方程:解的個數如何隨參數改變。
- 理解「代數解」與「數值近似解」的差別。
我們會一邊用 SymPy 計算,一邊連結到高中與大一程度的數學觀念, 並透過幾個啟發性的例子,體會方程與函數圖形的關係。
3.1 匯入 SymPy 與符號設定¶
先匯入 SymPy,並建立需要的符號變數:
import sympy as sp
sp.init_printing()
x, y, z = sp.symbols('x y z')
a, b, c = sp.symbols('a b c')
x, y, z, a, b, c
eq1 = sp.Eq(2*x + 3, 7)
solution1 = sp.solve(eq1, x)
eq1, solution1
如果方程是已經寫成「= 0」的形式,也可以直接把表達式丟進 solve,
SymPy 會理解成要解這個表達式等於 0 的根:
eq2_expr = 3*x - 9 # 代表 3x - 9 = 0
sp.solve(eq2_expr, x)
eq_quad = sp.Eq(x**2 - 5*x + 6, 0)
sp.solve(eq_quad, x)
也可以不顯示 Eq,直接解多項式的根:
sp.solve(x**2 - 5*x + 6, x)
如果系數帶有參數(例如 $ax^2 + bx + c = 0$), SymPy 會給出包含參數的解:
a, b, c = sp.symbols('a b c')
eq_general = a*x**2 + b*x + c
sp.solve(eq_general, x)
你可以看到熟悉的求根公式:
$x = \dfrac{-b \pm \sqrt{b^2 - 4ac}}{2a}$。
這讓我們理解:教科書上的公式其實可以被電腦符號運算系統「重新推導」出來。
3.4 一般非線性方程與 solveset¶
除了多項式方程之外,我們也會遇到包含三角函數、指數、對數等的方程。 例如:
$\sin x = \dfrac{1}{2}$。
這種方程通常有無限多解,使用 solve 可能只得到部分解,
這時適合改用 solveset,它會以集合形式給出一般解:
eq_trig = sp.Eq(sp.sin(x), sp.Rational(1, 2))
sp.solveset(eq_trig, x)
solveset 對於簡單的代數方程也適用:
sp.solveset(x**2 - 5*x + 6, x)
3.5 聯立一次方程組:solve¶
考慮二元一次聯立方程:
\begin{cases} x + y = 3 \\ x - y = 1 \end{cases}
在 SymPy 中,我們可以把每一條方程寫成表達式(默認等於 0)或 Eq,
再用 sp.solve([方程列表], [未知數列表]):
x, y = sp.symbols('x y')
solutions_2 = sp.solve([x + y - 3, x - y - 1], [x, y])
solutions_2
再看一個 3 元聯立系統:
\begin{cases} x + y + z = 6 \\ 2x - y + z = 3 \\ x + 2y - z = 4 \end{cases}
x, y, z = sp.symbols('x y z')
solutions_3 = sp.solve([
x + y + z - 6,
2*x - y + z - 3,
x + 2*y - z - 4
], [x, y, z])
solutions_3
3.6 使用矩陣觀點解線性方程¶
線性代數中,我們把線性方程組寫成矩陣形式 $A\vec{x} = \vec{b}$。
SymPy 的 Matrix 提供了 rref()(列簡化階梯形)、解線性系統等工具。
以剛才的三元方程為例:
A = sp.Matrix([
[1, 1, 1],
[2, -1, 1],
[1, 2, -1]
])
b_vec = sp.Matrix([6, 3, 4])
print("係數矩陣 A:")
display(A)
print("常數向量 b:")
display(b_vec)
print("增廣矩陣 [A|b] 的列簡化:")
Aug = A.row_join(b_vec)
Aug_rref, pivots = Aug.rref()
display(Aug_rref)
pivots
係數矩陣 A:
常數向量 b:
增廣矩陣 [A|b] 的列簡化:
從列簡化的結果中,我們可以看出:
- 如果主對角線上每一列的主元都存在,則有唯一解。
- 若出現全 0 = 非 0 的行,則無解。
- 若有自由變數,則有無限多解(解集合是一個線性子空間或平移的子空間)。
在後續的線性代數課程中,你會更深入地使用這種矩陣觀點。
3.7 代數解 vs 數值近似解:nsolve¶
有些方程難以用「封閉公式」表示解(特別是高次方程或含有多種特殊函數), 這時我們會尋求數值近似解。
SymPy 提供 nsolve 來做數值求解,需要給定一個「初始猜測值」:
from sympy import nsolve
eq_nonlin = sp.Eq(sp.exp(x) - x**2, 0)
eq_nonlin
我們可以嘗試不同的初始值,找到不同的解:
root1 = nsolve(sp.exp(x) - x**2, 0) # 以 0 附近為起點
root2 = nsolve(sp.exp(x) - x**2, 2) # 以 2 附近為起點
root1, root2
這裡得到的是小數近似值。若需要更高精度,可以指定 nsolve 的 prec 或再用 sp.N 增加位數。
3.8 啟發性例子一:兩個函數的交點 = 方程解¶
考慮函數:
$y_1 = x^2$ 與 $y_2 = 2x + 3$。
它們的交點滿足:
$x^2 = 2x + 3$。
也就是:
$x^2 - 2x - 3 = 0$。
先用 SymPy 找出交點的 $x$ 值,再思考對應的圖形關係。
x = sp.symbols('x')
eq_cross = sp.Eq(x**2, 2*x + 3)
xs = sp.solve(eq_cross, x)
xs
若你的環境支援 sp.plot(如 Jupyter Notebook),可以畫圖輔助觀察:
# 此繪圖在某些線上環境可能無法顯示,但在本機 Jupyter 中通常可正常使用
sp.plot(x**2, 2*x + 3, (x, -5, 5), legend=True)
<sympy.plotting.backends.matplotlibbackend.matplotlib.MatplotlibBackend at 0x7f35cecb5400>
思考:
- 方程的「解」與圖形上的「交點」有什麼關係?
- 如果把右邊改成 $y_2 = 2x - 3$,交點個數會如何改變? (試著自己改程式,重新求解並繪圖。)
3.9 啟發性例子二:非線性聯立方程¶
考慮平面上的兩條曲線:
$\begin{cases} x^2 + y^2 = 5 \\ y = x + 1 \end{cases}$
幾何意義:一個圓與一條直線的交點。使用 solve 來求解:
x, y = sp.symbols('x y')
solutions_circle = sp.solve([
x**2 + y**2 - 5,
y - (x + 1)
], [x, y])
solutions_circle
這個例子展示了:聯立方程不一定要「一次」,也可以是非線性的曲線與曲線相交問題。 你可以試著修改常數 5 或右邊的線性關係,觀察交點數量如何改變。
a = sp.symbols('a')
expr_param = x**2 - a*x + 1
sp.solve(expr_param, x)
判別式為 $D = a^2 - 4$,解的型態隨 $a$ 不同而變:
- 若 $|a| > 2$,則兩個不等的實根。
- 若 $|a| = 2$,則一個重根。
- 若 $|a| < 2$,則兩個共軛複數根(無實根)。
我們可以用 SymPy 來驗證判別式:
D = sp.discriminant(expr_param, x)
D
你可以試著代入不同的 $a$ 值,例如 a=0, 1, 2, 3,觀察實根的個數:
for val in [0, 1, 2, 3, -3]:
sol = sp.solve(expr_param.subs(a, val), x)
print(f"a = {val} 時,解 = {sol}")
a = 0 時,解 = [-I, I] a = 1 時,解 = [1/2 - sqrt(3)*I/2, 1/2 + sqrt(3)*I/2] a = 2 時,解 = [1] a = 3 時,解 = [3/2 - sqrt(5)/2, sqrt(5)/2 + 3/2] a = -3 時,解 = [-3/2 - sqrt(5)/2, -3/2 + sqrt(5)/2]
這個例子讓我們看到「參數」對方程解的影響, 在許多應用問題(如物理、工程、經濟模型)中,這種思維非常重要。
3.11 本章小結¶
本章你學到了:
- 如何用
Eq與solve解一元一次、二次及一般代數方程。 - 使用
solveset處理具有無限多解的方程,尤其是三角方程。 - 使用
solve解二元、三元聯立方程,並搭配Matrix理解其線性代數結構。 - 使用
nsolve對難以求得封閉解的方程做數值近似。 - 從幾何觀點理解方程解(曲線交點)、以及參數如何影響解的個數。
請記得:
- 方程的「解」不只是一個數字,更對應到幾何圖形、物理或現實情境中的某種狀態。
- SymPy 幫助我們快速求解與實驗,但理解條件、參數與解的意義仍需你的數學直覺與判斷。
3.12 練習題¶
請在本 Notebook 中新增儲存格,試著完成以下練習:
一元一次方程
(a) 使用Eq解方程 $3x - 7 = 2x + 5$。
(b) 將方程改寫為「= 0」的形式,再直接用solve(表達式, x)解一次,確認結果相同。一元二次方程
使用solve解下列方程:
(a) $x^2 + 4x + 4 = 0$
(b) $2x^2 - 3x - 2 = 0$
並觀察解的型態(重根、兩實根、無實根)。三角方程與
solveset
(a) 使用solveset解 $\sin x = 0$。
(b) 使用solveset解 $\cos x = \dfrac{1}{2}$。
思考:這些解如何在單位圓上解釋?二元聯立方程
解聯立方程:
$\begin{cases} 2x + 3y = 7 \\ x - y = 1 \end{cases}$
並檢查解是否滿足兩條方程(可用subs代入檢查)。矩陣方法
令 $\begin{cases} x + 2y + 3z = 1 \\ 2x - y + z = 0 \\ 3x + y - z = 4 \end{cases}$
(a) 寫出係數矩陣 $A$ 與常數向量 $b$。
(b) 使用Matrix形成增廣矩陣,計算rref()。
(c) 比較rref()的結果與solve的解是否一致。數值解
nsolve
(a) 使用nsolve解方程 $\cos x = x$,試著從不同初始值出發(例如 0、1、2),觀察找到的解。
(b) 試著解 $e^{-x} = x$,同樣比較不同初始值(例如 0、1、2)。參數與解的個數(加分題)
(a) 考慮方程 $x^2 + 2ax + 1 = 0$,計算其判別式並分別討論 $a > 0$、$a = 0$、$a < 0$ 的解的型態。
(b) 寫一小段文字說明:為什麼「判別式」能決定二次方程的解的個數與型態?
完成這些練習後,你應該對『方程』與『解』有更深入的直觀,也更熟悉如何利用 SymPy 作為解題與探索的工具。