当前位置: 华文问答 > 数码

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