JOVANA
Explore Library Glossary Getting Started Three Levels Fields How it works Mission
Join the mission
All guides

數值微分與最佳步長

若拿不到導數的公式,你可以從幾個函數值來估計它——但這裡會發生一件怪事:把步長 h 縮小先是有幫助,接著就不再有幫助,再小反而更糟。本篇將精確說明箇中原因,以及那個甜蜜點落在哪裡。

從導數的定義,到一個你能真正算的配方

我們以微積分當年開場的方式,揭開「積分與微分」這一級:從極限 f'(x) = 當 h 趨於零時 (f(x + h) - f(x)) / h 的極限。在紙上你取這個極限,得到一個精確公式。但假設 f 是某種你只能去求值的東西——一個由模擬吐出的數值、一個沒有符號形式的黑箱函數、或一筆實驗資料。那麼就沒有極限可取了;你能做的只是挑一個很小但非零的 h,去算那個商。捨棄極限、保留一個有限的 h,就把定義變成了一條有限差分公式,這是數值微分的主力。前向差分 (f(x + h) - f(x)) / h 是最簡單的一條:它只要兩個函數值,並用一條鄰近割線的斜率,去近似切線的斜率。

這條割線的斜率錯得有多離譜?支撐了整座微積分階梯的泰勒定理,給出精確的答案。把 f(x + h) = f(x) + h*f'(x) + (h^2 / 2)*f''(x) + ... 展開,再解出 f'(x):前向差分等於 f'(x) + (h/2)*f''(x) + ...。所以它所犯的誤差——也就是截斷誤差,截斷那條無窮泰勒級數所付的代價——約為 (h/2)*f''(x),是 O(h) 的。把 h 減半,誤差就減半。這是一個一階方法:主導誤差項與 h 的一次方成正比。

一個對稱的把戲,免費換來多一階

我們能在同樣的成本下做得更好。不要只往前跨,往兩邊都跨,改用中心差分 (f(x + h) - f(x - h)) / (2h)。把兩個泰勒展開都寫出來:f(x + h) 與 f(x - h) 共用相同的偶次項,但它們的奇次項(那些 h*f' 與 (h^3/6)f''' 的部分)變號。相減時 f(x) 項消掉了,而且連*那個毀掉前向差分的 h^2*f'' 項也消掉了。剩下的主導誤差約為 -(h^2 / 6)*f'''(x),是 O(h^2) 的。這就是回報:一條二階公式。如今把 h 減半,誤差不是減半,而是減為四分之一。

同一套「泰勒相減」的把戲,生出一整個差分模板的動物園:把 x、x ± h、x ± 2h 處的值,配上巧妙挑選的權重相加,你就能消掉越來越高的誤差項,達到四階精度甚至更高;或者用 (f(x + h) - 2*f(x) + f(x - h)) / h^2 來估計二階導數。那些加了權重的取樣點花樣,正是微分方程那幾級所倚賴的有限差分模板——它們把導數變成網格上的算術。

劇情逆轉:h 越小不一定越好

截斷誤差的故事說:把 h 縮小,誤差就消失,所以盡你所能把 h 弄到最小。這個建議是個陷阱,而看清為什麼,正是本篇的核心。問題在於我們做的不是實數算術——我們做的是浮點數算術,其中每個 f(x) 都帶著一個約莫單位捨入誤差 u(雙精度下約 1e-16)量級的微小相對捨入誤差。當 h 很小時,f(x + h) 與 f(x) 是兩個幾乎相等的數,而相減兩個幾乎相等的數,正是教科書裡災難性抵消的經典配方:領頭的位數相符而互相湮滅,剩下的差由原始值裡的捨入雜訊主宰。

把它量化。每次對 f 求值,準到約 u*|f(x)| 的絕對誤差。分子裡的那個差帶著同樣的絕對雜訊,但我們接著要除以 h,於是導數估計裡的捨入誤差便像 u*|f(x)| / h 那樣增長。注意方向:當 h 縮小,這一項反而變大。同時截斷誤差像 h^2(中心)或 h(前向)那樣縮小。於是總誤差是兩個朝相反方向拉扯的項之和——一個隨 h 下降,一個隨 h 下降而上升。這場拔河,就是著名的步長取捨

total error(h)  ~   C_trunc * h^2     +     u * |f| / h
                    \__________/           \__________/
                  truncation (falls)      round-off (rises)

  large h: truncation dominates  ->  decrease h
  small h: round-off  dominates  ->  increase h
  best h: the two are balanced (a V-shaped error curve)
中心差分的兩個誤差來源。把總誤差對 h 畫在雙對數軸上,你會得到一個 V 形(或打勾形):截斷帶來斜率 +2 的下坡,捨入帶來斜率 -1 的上坡,兩者交會於唯一一個最佳 h。

找出那個甜蜜點

因為中心差分的總誤差(大致)是 C*h^2 + u*M/h,其中 M 約為 |f| 的量級,我們可以用微積分教過的方式找極小:對 h 求導、令其為零、解出來。結果是 h_opt 正比於 u 的立方根——約 u^(1/3),雙精度下大致 1e-5——而在那個 h 處,可達到的最小誤差本身約為 u^(2/3),大致 1e-11。請讀兩遍:雙精度準到約 16 位,中心差分最好也只能做到約 11 位正確數字;而一階前向差分更差,最佳 h ~ u^(1/2) ~ 1e-8,誤差地板約為 u^(1/2) ~ 1e-8。無論你怎麼調 h,都永遠無法從一條樸素的有限差分裡,把完整的機器精度找回來。

  1. 寫下總誤差模型:截斷(C * h^p,前向 p = 1,中心 p = 2)加上捨入(u * |f| / h)。
  2. 對 h 求這個和的導數並令其為零,使這兩個競爭的項取得平衡。
  3. 解出最佳步長:中心差分 h_opt ~ u^(1/3),前向差分 ~ u^(1/2)。
  4. 代回去讀出誤差地板:中心約 u^(2/3)(~1e-11),前向約 u^(1/2)(~1e-8)——那條公式所能達到的最佳精度。

我們落腳何處——以及這一級接下來往哪走

退一步看,這個教訓的適用範圍遠不止於導數。科學計算中的精度,幾乎從不被單一誤差卡住瓶頸;它是一場平衡——介於一個你能藉細化(這裡是 h)來控制的離散化誤差,與一個細化打不過、且最終會被放大的浮點誤差之間。每當一個方法把鄰近的量相減、再除以一個小數,同一條 V 形曲線就會重現。數值微分是初遇這個模式最乾淨的地方,因為兩半都那麼容易寫下來。它也帶著一種令人謙卑的誠實:這裡每個值都是近似,捨入地板是硬體立下的一堵牆,再怎麼巧妙地挑 h,也別假裝不是如此。

那麼,我們能打破那道地板嗎?從這裡岔出兩條路,這一級兩條都會走。下一篇講理查森外推,它仍待在有限差分裡,卻玩一個更聰明的局:在 h 與 h/2 處各算一次中心差分,再把兩者組合起來,使主導的 h^2 誤差項精確抵消,一躍而至 O(h^4) 精度,而完全不需要一個危險地小的 h。另一條路,也就是這一級的壓軸,徹底揚棄差分:自動微分讓導數資訊穿過那段計算 f 的程式碼本身傳播,交出一個準到完整機器精度的導數,沒有 h、沒有截斷誤差、也完全沒有抵消——本篇的這場取捨,在那裡根本不存在。兩者,都是對我們剛剛撞上的那堵牆的回答。