跳轉到

1.1 電腦如何做數學#

概念說明#

人類做數學時,使用的是符號與推理:我們寫下 a² + b² = c²,並用邏輯證明它。電腦做數學的方式完全不同——它只會做「有限步驟的位元運算」。任何數學問題要交給電腦,都必須先被轉換成三個部分:

  1. 資料表示:把數學物件(整數、實數、多項式、矩陣)編碼成一串位元。
  2. 演算法:把求解過程拆解成明確、有限、可機械執行的步驟。
  3. 誤差/複雜度控制:明確知道計算有多快、答案有多準。

以「計算 √2」為例,人類知道它是一個無理數,等於 2 的算術平方根;但電腦無法「直接」輸出一個無限不循環小數,它只能輸出某個有限精度的近似值,例如 1.4142135623730951。這個近似值是怎麼來的?答案是靠一個收斂的迭代演算法,例如巴比倫法(即牛頓法在 f(x) = x² − 2 上的特例):反覆令 x_{n+1} = (x_n + 2/x_n) / 2,每迭代一次有效位數大約翻倍。

演算法步驟#

一個典型的數學演算法設計流程如下:

  1. 形式化問題:給定什麼輸入、要求什麼輸出、答案的正確標準是什麼。
  2. 選擇表示法:用什麼資料結構存數學物件(陣列存多項式係數、二維陣列存矩陣)。
  3. 設計核心步驟:找到能逼近或直接計算答案的迭代或遞迴規則。
  4. 分析收斂性與誤差:證明步驟會收斂,並估計誤差上界。
  5. 實作與測試:用程式碼實作,並用已知答案的案例驗證。

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/ε))。

練習#

  1. 修改 babylon_sqrt,使其能正確處理 0 < x < 1 的情況(提示:√0.01 = 0.1,想想初始猜測該怎麼選)。
  2. 用同一個架構,把迭代式改成 x_{n+1} = (2*x_n + x/x_n²)/3,計算立方根 ∛x,並驗證 ∛27 ≈ 3。
  3. 比較迭代 3 次、5 次、10 次的結果與 math.sqrt 的差異(用 abs(a-b)),畫出誤差隨迭代次數下降的表格,驗證「正確位數翻倍」的說法。