Solve the nth derivative of a given function by using Richardson extrapolation method. (線上執行) (原始碼下載)
一函數在某區間的積分值可以利用 Romberg integration 求得,而一函數在某點的微分值可以利用有限差分(finite difference)求出。有限差分可以分為前向差分(forward difference)、後向差分(backward difference)、中央差分(central difference),以及結合外插觀念與差分原理所衍生出較準確之理查生外插法(Richardson extrapolation),在此主要介紹理查生外插法,此法主要利用較低準確度的差分法,先求得不同 mesh size 之下的導數值,再利用外插法消去影響誤差最大之數值,而求得較準確之導數值。
以下的副程式先使用準確度為 O(h2) 之中央差分法,依序求得 mesh size 為 h、h/2、h/4、h/8.....etc之導數值,再利用理查生外插法求得較準確的導數值。使用以下副程式時,若初始 h 設的太小或是欲求較高階之導數,可能會發生溢位或除以零的問題,必須特別注意。
副程式:
Option Explicit 'x=欲求某點之導數 'h=初始 mesh size (不可設的太小) 'n=導數之階數 'tol=容許誤差 Public Function Richardson(x As Double, h As Double, n As Long, tol As Double) As Double Dim i As Long, j As Long, T() As Double, L As Long ReDim T(1 To 3) As Double T(1) = CDn(x, h, n) T(2) = CDn(x, h / 2, n) T(3) = CDn(x, h / 4, n) j = 3 Do While Abs(T(UBound(T)) - T(UBound(T) - 2)) > tol For i = 2 To UBound(T) Step 2 T(i - 1) = T(i) Next T(2) = CDn(x, h / (2 ^ j), n) ReDim Preserve T(1 To UBound(T) + 2) For L = 2 To j If L <> j Then T(L * 2) = ((4 ^ (L - 1)) * T(L * 2 - 2) - T(L * 2 - 3)) / ((4 ^ (L - 1)) - 1) Else T(UBound(T)) = ((4 ^ (L - 1)) * T(UBound(T) - 1) - _ T(UBound(T) - 2)) / ((4 ^ (L - 1)) - 1) End If Next j = j + 1 Loop Richardson = T(UBound(T)) End Function其中 CDn 函數請參閱本站的 Solve the nth derivative of a given function by using central difference method.
範例:
例如要求 f=ex 在 x=2 的微分值,使用初始 mesh size=1.0 可以寫出以下程式碼:
'對於不同的函數 f , 只要更改以下副程式即可 Public Function f(x As Double) As Double f = Exp(x) End FunctionPrivate Sub Command1_Click() Dim x As Double, h As Double, tol As Double tol = 0.00001 x = InputBox("請輸入 x 值", , "2") h = InputBox("請輸入間距 h 值", , "1") Debug.Print "一階導數 = " & Richardson(x, h, 1, tol) Debug.Print "二階導數 = " & Richardson(x, h, 2, tol) Debug.Print "三階導數 = " & Richardson(x, h, 3, tol) Debug.Print "四階導數 = " & Richardson(x, h, 4, tol) End Sub執行後在即時運算視窗可得以下結果:
一階導數 = 7.38905609850807 二階導數 = 7.38905609870055 三階導數 = 7.38905609655925 四階導數 = 7.38905750432817此題正確結果應為 7.389056099,由此可知愈高階導數所得結果誤差愈大,主要誤差來自於 truncation error,少部分誤差來自於 roundoff error。一般來說減小 mesh size 可以增加計算結果的準確度,但是 mesh size 小至某一程度後,會使得 roundoff error 的效應變得很明顯,因此太小的 mesh size 不見得能得到最準確之結果。理查生外插法所求得之導數值一定比前向、後向、以及中央差分法來得準確,但是所需執行時間較長
以上副程式只適用於解決連續函數之微分問題,對於一不連續函數或是具有奇異點(singularity)之函數將不適用;對於一週期性函數(例如:sin x),mesh size 不可等於該函數之週期;對於某些較特殊之函數,必須注意該函數之值域(range),例如 f=log(x),欲求 x=0.1 時之微分值,使用 mesh size=0.2,此時若用後向差分或中央差分將會產生問題,因為 x< 0 並不在 x 的定義域內(domain),因此也不在 log(x) 的值域內,此時應該使用前向差分才不致發生這類問題。
This page was written by Jaric on Jul. 31 , 1999. All rights reserved.