第 5 章 數列與遞迴關係¶

本章重點:

  • 了解「數列」的觀念:以整數 $n$ 為索引的函數 $a_n$。
  • 使用 Python 產生數列的前若干項,觀察規律。
  • 認識常見的數列:等差數列、等比數列,以及其通項與部分和公式。
  • 了解「遞迴關係」如何定義數列,並用程式與 SymPy 解線性遞迴。
  • 把數列視為「離散函數」,與現實情境(存款、人口、誤差)連結。

在 Jupyter Notebook 中,數列是一個非常適合實驗與觀察的主題, 你可以用程式快速生成大量項目,來驗證自己的猜想。

5.1 數列的基本觀念¶

在數學上,可以把數列看成一個定義在正整數上的函數:

$a_1, a_2, a_3, \dots$ 或 $a_n$。

在 Python 中,我們通常會用「列表(list)」或是「函數加迴圈」的方式來表示與產生數列。以下是一個簡單例子:

$a_n = n^2$,也就是:$1, 4, 9, 16, 25, \dots$

In [1]:
def square_sequence(n_max):
    seq = []
    for n in range(1, n_max+1):
        seq.append(n**2)
    return seq

square_sequence(10)
Out[1]:
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

5.2 用 Python 產生數列:基本技巧¶

我們可以用 list comprehension 更精簡地寫出同樣的數列生成方式:

In [2]:
[n**2 for n in range(1, 11)]
Out[2]:
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

再看一個例子:等差數列 $a_n = 2n - 1$,也就是所有奇數:$1, 3, 5, 7, 9, \dots$

In [3]:
[2*n - 1 for n in range(1, 11)]
Out[3]:
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]

5.3 等差數列:通項與部分和¶

一個等差數列的形式為:

$a_n = a_1 + (n-1)d$,

其中 $a_1$ 為首項,$d$ 為公差。

前 $n$ 項和為:

$S_n = \dfrac{n}{2}(a_1 + a_n)$ 或 $S_n = \dfrac{n}{2}[2a_1 + (n-1)d]$。

我們可以用 Python 實驗這個公式是否正確。先用程式逐項相加:

In [4]:
def arithmetic_sequence(a1, d, n_max):
    return [a1 + (n-1)*d for n in range(1, n_max+1)]

seq = arithmetic_sequence(a1=3, d=2, n_max=10)
seq
Out[4]:
[3, 5, 7, 9, 11, 13, 15, 17, 19, 21]

用迴圈計算前 $n$ 項和:

In [5]:
def partial_sum(seq, n):
    return sum(seq[:n])

for n in range(1, 6):
    print(f"n = {n}, S_n =", partial_sum(seq, n))
n = 1, S_n = 3
n = 2, S_n = 8
n = 3, S_n = 15
n = 4, S_n = 24
n = 5, S_n = 35

接著,用公式計算 $S_n$,檢查是否一致:

In [6]:
def arithmetic_sum_formula(a1, d, n):
    an = a1 + (n-1)*d
    return n*(a1 + an)/2

for n in range(1, 6):
    s_list = partial_sum(seq, n)
    s_formula = arithmetic_sum_formula(3, 2, n)
    print(f"n = {n}, 列表加總 = {s_list}, 公式 S_n = {s_formula}")
n = 1, 列表加總 = 3, 公式 S_n = 3.0
n = 2, 列表加總 = 8, 公式 S_n = 8.0
n = 3, 列表加總 = 15, 公式 S_n = 15.0
n = 4, 列表加總 = 24, 公式 S_n = 24.0
n = 5, 列表加總 = 35, 公式 S_n = 35.0

5.4 等比數列:通項與部分和¶

等比數列的形式為:

$a_n = a_1 r^{n-1}$,

其中 $r$ 為公比。

若 $r \ne 1$,前 $n$ 項和為:

$S_n = a_1 \dfrac{1-r^n}{1-r}$。

我們同樣用 Python 實驗此公式,例:$a_1 = 1, r = 2$,數列為 $1, 2, 4, 8, 16, \dots$

In [7]:
def geometric_sequence(a1, r, n_max):
    return [a1 * r**(n-1) for n in range(1, n_max+1)]

gseq = geometric_sequence(a1=1, r=2, n_max=10)
gseq
Out[7]:
[1, 2, 4, 8, 16, 32, 64, 128, 256, 512]

比較「逐項加總」與「公式」:

In [8]:
def geometric_sum_formula(a1, r, n):
    if r == 1:
        return a1 * n
    return a1 * (1 - r**n) / (1 - r)

for n in range(1, 6):
    s_list = sum(gseq[:n])
    s_formula = geometric_sum_formula(1, 2, n)
    print(f"n = {n}, 列表加總 = {s_list}, 公式 S_n = {s_formula}")
n = 1, 列表加總 = 1, 公式 S_n = 1.0
n = 2, 列表加總 = 3, 公式 S_n = 3.0
n = 3, 列表加總 = 7, 公式 S_n = 7.0
n = 4, 列表加總 = 15, 公式 S_n = 15.0
n = 5, 列表加總 = 31, 公式 S_n = 31.0

5.5 用 SymPy 表示數列的通項與和¶

SymPy 提供符號化的「求和」功能 summation,可用來推導數列和的公式。

先匯入所需符號:

In [9]:
import sympy as sp
sp.init_printing()

n, a1, d, r = sp.symbols('n a1 d r', integer=True, positive=True)
n
Out[9]:
$\displaystyle n$

以等差數列 $a_k = a_1 + (k-1)d$ 為例,考慮其前 $n$ 項和:

$S_n = \sum_{k=1}^n [a_1 + (k-1)d]$。

In [10]:
k = sp.symbols('k', integer=True, positive=True)
a_k_arith = a1 + (k-1)*d
Sn_arith = sp.summation(a_k_arith, (k, 1, n))
Sn_arith
Out[10]:
$\displaystyle d \left(\frac{n^{2}}{2} + \frac{n}{2}\right) + n \left(a_{1} - d\right)$

SymPy 給出的結果就是熟悉的等差數列部分和公式。

對等比數列 $a_k = a_1 r^{k-1}$ 做類似操作:

In [11]:
a_k_geom = a1 * r**(k-1)
Sn_geom = sp.summation(a_k_geom, (k, 1, n))
Sn_geom
Out[11]:
$\displaystyle \frac{a_{1} \left(\begin{cases} n & \text{for}\: r = 1 \\\frac{r - r^{n + 1}}{1 - r} & \text{otherwise} \end{cases}\right)}{r}$

5.6 遞迴關係:用 Python 迴圈定義數列¶

很多數列不是直接給出通項公式,而是給出「前後項的關係」, 這樣的規則稱為遞迴關係(recurrence relation)。

例如費波那契數列:

$a_1 = 1, a_2 = 1, a_{n} = a_{n-1} + a_{n-2}$(對 $n \ge 3$)。

我們可以用 Python 實作:

In [12]:
def fibonacci(n_max):
    a = {1: 1, 2: 1}
    for n in range(3, n_max+1):
        a[n] = a[n-1] + a[n-2]
    # 回傳列表形式
    return [a[n] for n in range(1, n_max+1)]

fibonacci(10)
Out[12]:
$\displaystyle \left[ 1, \ 1, \ 2, \ 3, \ 5, \ 8, \ 13, \ 21, \ 34, \ 55\right]$

你可以把定義換成:$a_1 = 2, a_2 = 5, a_n = a_{n-1} + a_{n-2}$,觀察數列如何改變。

5.7 用 SymPy 解線性遞迴:rsolve¶

SymPy 提供 rsolve 來處理某類型的遞迴關係(特別是線性遞迴)。

例如:

$a_n = 2a_{n-1}$,且 $a_0 = 3$。

這其實是一個等比數列,通項為 $a_n = 3\cdot 2^n$。試著用 rsolve 得到同樣結果。

In [13]:
from sympy import Function, rsolve

n = sp.symbols('n', integer=True)
a = Function('a')

recurrence = sp.Eq(a(n), 2*a(n-1))
initial = {a(0): 3}
solution = rsolve(recurrence, a(n), initial)
solution
Out[13]:
$\displaystyle 3 \cdot 2^{n}$

再看一個稍微複雜的例子:

$a_n - 3a_{n-1} + 2a_{n-2} = 0$,且 $a_0 = 1, a_1 = 2$。

這是一個二階線性遞迴,我們用 rsolve:

In [14]:
a = Function('a')
recurrence2 = sp.Eq(a(n) - 3*a(n-1) + 2*a(n-2), 0)
initial2 = {a(0): 1, a(1): 2}
solution2 = rsolve(recurrence2, a(n), initial2)
solution2
Out[14]:
$\displaystyle 2^{n}$

你可以把這個結果展開、簡化,看看是否可以寫成某種組合形式,例如 $c_1 \cdot 2^n + c_2 \cdot 1^n$ 之類的表達方式。

5.8 啟發性例子一:存款與利息(等比數列的應用)¶

假設你把 10,000 元存入銀行,每年利率 5%(不再追加存款), 每年結算一次並複利。則第 $n$ 年末的存款金額為:

$a_n = 10000 (1.05)^{n}$。

我可以用 Python 來產生前 10 年的金額:

In [15]:
principal = 10000
rate = 1.05

balance = [principal * rate**n for n in range(0, 11)]
for year, money in enumerate(balance):
    print(f"第 {year} 年末:{money:.2f} 元")
第 0 年末:10000.00 元
第 1 年末:10500.00 元
第 2 年末:11025.00 元
第 3 年末:11576.25 元
第 4 年末:12155.06 元
第 5 年末:12762.82 元
第 6 年末:13400.96 元
第 7 年末:14071.00 元
第 8 年末:14774.55 元
第 9 年末:15513.28 元
第 10 年末:16288.95 元

你可以思考:

  • 這是一個等比數列,公比是什麼?
  • 若利率改為 2%,或改成每年定期再存入固定金額,會形成什麼樣的遞迴關係?

這個例子將在機率與財務相關的課程中反覆出現。

5.9 啟發性例子二:人口成長與飽和模型(簡化版)¶

最簡單的人口成長模型是假設每年成長固定比例,形成等比數列:

$P_{n} = (1+r) P_{n-1}$。

若考慮「環境負荷上限」,可以改用較為複雜的遞迴,例如 logistic 類型:

$P_{n} = P_{n-1} + r P_{n-1}(1 - \dfrac{P_{n-1}}{K})$,

其中 $K$ 是環境承載量。雖然這個模型比較超出高中範圍,但我們可以用 Python 試著玩玩看,觀察行為:

In [16]:
def logistic_growth(P0, r, K, n_max):
    P = [P0]
    for n in range(1, n_max+1):
        P_prev = P[-1]
        P_new = P_prev + r * P_prev * (1 - P_prev / K)
        P.append(P_new)
    return P

P_values = logistic_growth(P0=10, r=0.2, K=100, n_max=20)
for n, val in enumerate(P_values):
    print(f"n = {n}, P_n ≈ {val:.4f}")
n = 0, P_n ≈ 10.0000
n = 1, P_n ≈ 11.8000
n = 2, P_n ≈ 13.8815
n = 3, P_n ≈ 16.2724
n = 4, P_n ≈ 18.9973
n = 5, P_n ≈ 22.0750
n = 6, P_n ≈ 25.5154
n = 7, P_n ≈ 29.3164
n = 8, P_n ≈ 33.4608
n = 9, P_n ≈ 37.9137
n = 10, P_n ≈ 42.6215
n = 11, P_n ≈ 47.5126
n = 12, P_n ≈ 52.5003
n = 13, P_n ≈ 57.4878
n = 14, P_n ≈ 62.3756
n = 15, P_n ≈ 67.0693
n = 16, P_n ≈ 71.4866
n = 17, P_n ≈ 75.5632
n = 18, P_n ≈ 79.2563
n = 19, P_n ≈ 82.5444
n = 20, P_n ≈ 85.4261

你會看到人口一開始成長很快,之後逐漸趨近於某個穩定值,這就是「飽和效應」。

這種離散時間的遞迴關係在生態學、經濟學與社會科學中都非常重要。

5.10 啟發性例子三:誤差與收斂序列¶

考慮數列:

$e_n = \left(\dfrac{1}{2}\right)^n$。

這是一個絕對值越來越小的數列,可以想像成「誤差」隨著迭代次數而下降。 例如在某種數值方法中,每一次迭代都將誤差減半。

我們用程式觀察其行為:

In [17]:
e = [0.5**n for n in range(0, 11)]
for n, val in enumerate(e):
    print(f"n = {n}, e_n = {val}")
n = 0, e_n = 1.0
n = 1, e_n = 0.5
n = 2, e_n = 0.25
n = 3, e_n = 0.125
n = 4, e_n = 0.0625
n = 5, e_n = 0.03125
n = 6, e_n = 0.015625
n = 7, e_n = 0.0078125
n = 8, e_n = 0.00390625
n = 9, e_n = 0.001953125
n = 10, e_n = 0.0009765625

你會發現 $e_n$ 越來越接近 0。這種數列在分析「演算法是否收斂」、「誤差是否會變小」時非常關鍵。

在後續的極限與微積分章節,我們會更正式地討論「收斂」的概念。

5.11 本章小結¶

本章你學到了:

  • 如何用 Python 產生數列的前幾項,並用程式輔助觀察規律。
  • 等差數列與等比數列的通項與部分和公式,並用 SymPy 驗證。
  • 遞迴關係如何定義數列,如何用迴圈實作,以及用 rsolve 求線性遞迴的解析解。
  • 數列在現實情境中的應用:存款複利、人口成長、誤差收斂等。

請記住:

  • 數列可以被看成「離散時間的函數」,與現實中的時間步驟、世代、迭代次數等概念密切相關。
  • Python 與 SymPy 可以作為你的「數列實驗室」,幫助你快速測試與理解各種數列行為。

5.12 練習題¶

請在本 Notebook 中新增儲存格,試著完成以下練習:

  1. 等差數列實作
    (a) 自行撰寫一個函數 arith_seq(a1, d, n_max) 產生前 n_max 項的等差數列。
    (b) 使用你的函數產生 $a_1 = 5, d = -2$ 的數列,印出前 10 項。
    (c) 用程式驗證部分和公式 $S_n = \dfrac{n}{2}[2a_1 + (n-1)d]$ 對這個例子是否成立。

  2. 等比數列與部分和
    (a) 產生 $a_1 = 3, r = \dfrac{1}{2}$ 的等比數列前 10 項。
    (b) 計算前 10 項和,並與公式 $S_n = a_1 \dfrac{1-r^n}{1-r}$ 比較。
    (c) 思考:當 $n$ 越來越大時,這個等比數列的部分和會趨近哪一個數?

  3. SymPy 的 summation
    (a) 使用 sp.summation 計算 $\sum_{k=1}^n k^2$ 的公式。
    (b) 試著用 n=1,2,3,4,5 代入檢查公式是否正確。

  4. 費波那契數列
    (a) 使用程式產生費波那契數列的前 15 項。
    (b) 計算連續兩項的比值 $\dfrac{a_{n+1}}{a_n}$,觀察其趨勢。
    (c) 查詢「黃金比例」的值,看看它與你觀察到的比值有何關係(可用 SymPy 的 sp.N(sp.GoldenRatio, 10) 顯示數值)。

  5. 使用 rsolve 解遞迴
    (a) 解遞迴關係:$a_n = 3a_{n-1} + 1$,且 $a_0 = 0$。
    使用 rsolve 找出通項公式。
    (b) 用迴圈實作這個遞迴,計算前 10 項,檢查是否與通項公式一致。

  6. 存款與定期定額(應用題)
    某人每年年末固定存入 5,000 元到年利率 3%(按年複利)的帳戶中,起始餘額為 0。
    (a) 寫出描述此存款情形的遞迴關係式。
    (b) 用 Python 實作,計算 10 年後帳戶中的金額。
    (c) 試著用數學推導或 SymPy 的 rsolve 找出一般項公式,並檢查與程式模擬結果是否一致。

  7. 加分題:收斂與發散的直觀
    (a) 使用程式產生數列 $a_n = (1.1)^n$ 與 $b_n = (0.9)^n$ 的前 20 項。
    (b) 觀察這兩個數列的行為:一個會越來越大,另一個會趨近 0。
    (c) 用文字寫下你對「收斂」與「發散」的直觀理解。

回首頁