1.1 電腦如何做數學#
概念說明#
人類做數學時,使用的是符號與推理:我們寫下 a² + b² = c²,並用邏輯證明它。電腦做數學的方式完全不同——它只會做「有限步驟的位元運算」。任何數學問題要交給電腦,都必須先被轉換成三個部分:
- 資料表示:把數學物件(整數、實數、多項式、矩陣)編碼成一串位元。
- 演算法:把求解過程拆解成明確、有限、可機械執行的步驟。
- 誤差/複雜度控制:明確知道計算有多快、答案有多準。
以「計算 √2」為例,人類知道它是一個無理數,等於 2 的算術平方根;但電腦無法「直接」輸出一個無限不循環小數,它只能輸出某個有限精度的近似值,例如 1.4142135623730951。這個近似值是怎麼來的?答案是靠一個收斂的迭代演算法,例如巴比倫法(即牛頓法在 f(x) = x² − 2 上的特例):反覆令 x_{n+1} = (x_n + 2/x_n) / 2,每迭代一次有效位數大約翻倍。
演算法步驟#
一個典型的數學演算法設計流程如下:
- 形式化問題:給定什麼輸入、要求什麼輸出、答案的正確標準是什麼。
- 選擇表示法:用什麼資料結構存數學物件(陣列存多項式係數、二維陣列存矩陣)。
- 設計核心步驟:找到能逼近或直接計算答案的迭代或遞迴規則。
- 分析收斂性與誤差:證明步驟會收斂,並估計誤差上界。
- 實作與測試:用程式碼實作,並用已知答案的案例驗證。
Python 程式碼範例#
以下用巴比倫法計算平方根,展示「迭代 + 誤差控制」的完整流程:
def babylon_sqrt(x, tol=1e-12, max_iter=100):
"""用巴比倫法計算 x 的平方根(x >= 1 的情形)"""
if x < 0:
raise ValueError("無法對負數開平方")
if x == 0:
return 0.0
g = max(x, 1.0) # 初始猜測
for i in range(max_iter):
new_g = (g + x / g) / 2 # 平均目前猜測與 x/g
print(f"第 {i+1} 次迭代: g = {new_g:.15f}")
if abs(new_g - g) < tol: # 收斂判定
return new_g
g = new_g
return g
root = babylon_sqrt(2)
print(f"√2 ≈ {root}")
print(f"檢驗: {root**2:.15f}") # 應接近 2
執行後你會看到猜測值迅速穩定在 1.4142135623730951——與內建 math.sqrt(2) 的結果完全一致。這說明:只要演算法設計得當,電腦可以在極少次迭代內得到幾乎「機器精度」的答案。
複雜度與誤差分析#
巴比倫法的收斂速度是二次收斂:若誤差為 ε,則一次迭代後誤差約為 ε²/C。換句話說,正確位數每次迭代大約翻倍。從 1 出發計算 √2,通常 5 次迭代內就達到雙精度浮點數的極限(約 16 位有效數字)。這也揭示了一個重要觀念:數值演算法的好壞,常用「達到目標精度需要幾次迭代」來衡量,而迭代次數又常是誤差容許值的對數函數,例如二次收斂時迭代次數約為 O(log log (1/ε))。
練習#
- 修改
babylon_sqrt,使其能正確處理 0 < x < 1 的情況(提示:√0.01 = 0.1,想想初始猜測該怎麼選)。 - 用同一個架構,把迭代式改成
x_{n+1} = (2*x_n + x/x_n²)/3,計算立方根 ∛x,並驗證 ∛27 ≈ 3。 - 比較迭代 3 次、5 次、10 次的結果與
math.sqrt的差異(用abs(a-b)),畫出誤差隨迭代次數下降的表格,驗證「正確位數翻倍」的說法。