當前位置: 華文問答 > 數碼

C中有沒有將一個函數轉變為另一個函數的函數(例如求導運算)?

2016-02-15數碼

題主本來的問題

c中有沒有將一個函數轉變為另一個函數的函數

答案是:有。

這一點在其他人的回答中,並沒有爭議。

C函數可以函數指標為輸入,以函數指標為輸出。

各位還沒形成共識的是題主所求的例子

(例如求導運算)

是否存在一個C語言的實作。

如有的答主已經指出,要回答這個問題,首先需要明確關於導數的定義。

假設使用者擁有一個可導函數。

@Belleve

同學給出的實作並不是求導運算,而是計算有限差分,即泰勒展開的一階項的近似值 \frac{df\left( x\right) }{dx}=\frac{f\left( x+\Delta x\right) -f\left( x\right) }{\Delta x}+O\left( \Delta x\right)

其中O\left( \Delta x\right) 被忽略掉了。

在許多不需要精確導數的套用中,差分法是適用的。

如果需要精確的導數,標準的方法是演算法微分(

Automatic differentiation

) 。與只計算泰勒展開一階項的有限差分不同,演算法微分利用鏈式法則,直接對計算程式求導。其實作方式大致分兩種

  • 編譯前的程式碼生成
    在許多套用中,使用者用來實作可導函數的庫函數都是可導的。例如 math.h 中的例如 sin/cosh 等函數的導數都是已知的。利用這一性質,使用者的可導函數可以被看作一個復合函數 (composite function),並用鏈式法則 (chain rule) 自動生成導數的計算程式碼。
    為C/C++提供的開源庫列表:www.Autodiff.org

  • 執行時的函數多載
    上一種方法需要對程式碼進行分析,實作難度堪比編譯器。另一種方法是透過函數多載。原理和上一種方法一樣,只是導數的計算方法是動態生成的,而非透過編譯前的靜態分析。也正因如此,這種實作雖然簡單,但執行效率要低一些。
    為C/C++提供的開源庫列表:www.Autodiff.org
  • 對於多變量的函數,演算法微分比起差分法可以快 n 倍,其中 n 是變量的個數。

    試想用有限差分計算有三個變量的的函數

    \frac{df\left( x,y,z\right) }{dx}=\frac{f\left( x+\Delta x,y,z\right) -f\left( x,y,z\right) }{\Delta x}+O\left( \Delta x\right)

    一次計算只能計算針對一個變量的近似導數值,要得到完整的導數需要計算三次。

    而使用鏈式法則計算導數的演算法微分只需一次計算。

    演算法微分的套用廣泛,尤其是在解最佳化問題的時候。機器學習演算法神經網絡的訓練步驟裏,導數的計算就是使用的演算法微分。許內送流量備援容錯機制流的神經網絡庫都提供題主所說的求導函數,這樣使用者就不必親自實作計算導數的程式。例如神經網絡的開源庫(

    https:// pypi.python.org/pypi/au tograd/1.0.4