文章

橢圓積分怎麼算:AGM 算法與冪級數展開

第一類橢圓積分 K(k) 沒有初等函數公式,但可以高效計算。本文介紹兩種方法:冪級數展開(適合小 k)與算術幾何平均(AGM)算法。AGM 每迭代一次有效位數倍增,只需約 10 步即可達到機器精度。

橢圓積分怎麼算:AGM 算法與冪級數展開

\(\require{physics}\)

上一篇說明了 $K(k)$ 無法用初等函數表示。但「無法用初等函數表示」不代表算不出來——只是需要適當的算法。

本篇介紹兩種計算 $K(k)$ 的方法:

  1. 冪級數展開:直接、透明,適合 $k$ 不太大時
  2. 算術幾何平均(AGM)算法:收斂極快,任意精度首選

方法一:冪級數展開

上一篇已推導出:

\[K(k) = \frac{\pi}{2}\sum_{n=0}^\infty \left[\frac{(2n)!}{4^n (n!)^2}\right]^2 k^{2n}\]

展開式:

\[K(k) = \frac{\pi}{2}\!\left[1 + \left(\frac{1}{2}\right)^{\!2} k^2 + \left(\frac{1\cdot 3}{2\cdot 4}\right)^{\!2} k^4 + \left(\frac{1\cdot 3\cdot 5}{2\cdot 4\cdot 6}\right)^{\!2} k^6 + \cdots\right]\]

誤差估計

截斷到 $k^{2N}$ 項,誤差量級為

\[\text{誤差} \sim \frac{\pi}{2}\left[\frac{(2N)!}{4^N (N!)^2}\right]^2 k^{2N+2} \cdot \frac{1}{1-k^2}\]

對 $k = 0.5$,取到 $k^6$ 項已有六位有效數字。但 $k \to 1$ 時收斂極慢(因為 $K(k)$ 本身趨向無限大),需要對數修正或其他方法。


方法二:算術幾何平均(AGM)算法

這個方法由高斯發現,是計算 $K(k)$ 最優雅也最高效的方式。

算術幾何平均(Arithmetic-Geometric Mean)

給定兩個正數 $a_0 > b_0 > 0$,定義迭代:

\[a_{n+1} = \frac{a_n + b_n}{2} \qquad\text{(算術平均)}\] \[b_{n+1} = \sqrt{a_n b_n} \qquad\text{(幾何平均)}\]

AM-GM 不等式保證 $a_{n+1} \ge b_{n+1}$,且兩數列會從上下同時夾擠,收斂到同一極限,記為

\[\text{AGM}(a_0, b_0) = \lim_{n\to\infty} a_n = \lim_{n\to\infty} b_n\]

收斂速度:平方收斂

AGM 的收斂是二次收斂(quadratic convergence):誤差 $\varepsilon_n = a_n - b_n$ 滿足

\[\varepsilon_{n+1} \approx \frac{\varepsilon_n^2}{8 a_0}\]

也就是每迭代一次,有效位數倍增。從初始誤差到機器精度(約 16 位),只需約 $\log_2 16 = 4$ 到 $5$ 次迭代就能達到;實際計算中約 $5$–$10$ 步即可達到雙精度。

相比之下,冪級數在 $k = 0.9$ 時需要數十項才能收斂到同樣精度。

AGM 與 $K(k)$ 的關係

高斯的發現:

\[\boxed{K(k) = \frac{\pi}{2\,\text{AGM}(1,\,k')}}\]

其中 $k’ = \sqrt{1 - k^2}$ 是補模數(complementary modulus)。

這個公式的推導依賴一個積分恆等式:

\[\int_0^{\pi/2}\frac{\dd{\phi}}{\sqrt{1 - k^2\sin^2\phi}} = \int_0^{\pi/2}\frac{\dd{\psi}}{\sqrt{1 - k_1^2\sin^2\psi}}\]

其中 $k_1 = (1 - k’)/(1 + k’)$ 是一次 AGM 迭代後的新模數。反覆應用這個恆等式,模數序列收斂到 $0$,此時 $K(0) = \pi/2$,整個過程中分母累積出 $\text{AGM}(1, k’)$。


手算範例:$K(1/\sqrt{2})$

$k = 1/\sqrt{2}$ 時 $k’ = \sqrt{1 - 1/2} = 1/\sqrt{2}$,所以

\[\text{AGM}(1, 1/\sqrt{2}) = ?\]
$n$$a_n$$b_n$$a_n - b_n$
0$1.000000$$0.707107$$0.292893$
1$0.853553$$0.840896$$0.012657$
2$0.847225$$0.847213$$0.000012$
3$0.847219$$0.847219$$< 10^{-11}$

表 1: $\text{AGM}(1, 1/\sqrt{2})$ 的迭代過程。三步就達到 11 位精度。

因此

\[K\!\left(\frac{1}{\sqrt{2}}\right) = \frac{\pi}{2 \times 0.847219} \approx 1.8541\]

與精確值 $1.8541\ldots$ 完全吻合。


Python 實作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import numpy as np

def K_AGM(k, tol=1e-15):
    """用 AGM 算法計算第一類完全橢圓積分 K(k)"""
    k_prime = np.sqrt(1 - k**2)
    a, b = 1.0, k_prime
    while abs(a - b) > tol * a:
        a, b = (a + b) / 2, np.sqrt(a * b)
    return np.pi / (2 * a)

def K_series(k, n_terms=20):
    """用冪級數計算 K(k),展開到 k^(2n_terms) 項"""
    result = 1.0
    coeff = 1.0
    k2 = k**2
    k2n = k2
    for n in range(1, n_terms + 1):
        coeff *= (2*n - 1) / (2*n)
        result += coeff**2 * k2n
        k2n *= k2
    return (np.pi / 2) * result

# 測試
for k in [0.0, 0.5, 0.9, 0.99]:
    val_agm = K_AGM(k)
    val_ser = K_series(k)
    print(f"k = {k:.2f} | AGM = {val_agm:.8f} | 冪級數 = {val_ser:.8f}")

輸出(參考):

1
2
3
4
k = 0.00 | AGM = 1.57079633 | 冪級數 = 1.57079633
k = 0.50 | AGM = 1.68575035 | 冪級數 = 1.68575035
k = 0.90 | AGM = 2.28058160 | 冪級數 = 2.28058160
k = 0.99 | AGM = 3.35655517 | 冪級數 = 3.35583782  ← 冪級數已有誤差

注意:$k = 0.99$ 時冪級數取 20 項仍有第五位的誤差,而 AGM 幾步就達到機器精度。

scipy.special.ellipk(m) 也是用 AGM 類算法實作的(注意:scipy 的參數是 $m = k^2$,不是 $k$ 本身)。


兩種方法比較

 冪級數展開AGM 算法
適用範圍$k$ 遠小於 $1$任意 $k \in [0, 1)$
收斂速度線性(每項增加一位)平方(每步位數倍增)
程式複雜度極簡單簡單(5–10 行)
大 $k$ 精度需要很多項幾步達機器精度
直覺透明度高(每項有意義)較低(需理解 AGM 恆等式)

實際應用中,$k < 0.7$ 時冪級數取 10 項已夠用;$k$ 更大時建議用 AGM。


小結

$K(k)$ 雖然沒有初等函數公式,但可以高效計算:

  • 冪級數:$K(k) = \frac{\pi}{2}\left[1 + k^2/4 + 9k^4/64 + \cdots\right]$,小 $k$ 時快速收斂
  • AGM 算法:$K(k) = \pi / (2\,\text{AGM}(1, \sqrt{1-k^2}))$,平方收斂,約 10 步達雙精度
  • scipy.special.ellipk(k**2) 可直接使用(注意參數是 $m = k^2$)

下一篇從單擺往上走一層:用相空間(phase space)來看懂單擺所有可能的運動——來回擺動、臨界軌道、整圈旋轉。

本文章以 CC BY 4.0 授權