C ++ - 如何编写函数,返回实值函数的导数,而不是导数的值

时间:2018-02-11 20:50:57

标签: c++

此函数计算X

处的函数Foo的推导值
double Deriv( double(* Foo)(double x), double X )
{
    const double mtDx = 1.0e-6;

    double x1 = Foo(X+mtDx);
    double x0 = Foo(X);

    return ( x1 - x0 ) / mtDx;
}

我想写一个Funktion,它不返回X的派生值,而是一个新函数,它是函数Foo的推导。

 xxxx Deriv( double(* Foo)(double x) )
{
    return Derivation of Foo;
}

然后就可以写了 SecondDeriv = Deriv(Deriv(Foo))

根据新标准在C ++中是否可以编写这样的函数? 我认为用旧标准来说这是不可能的。

3 个答案:

答案 0 :(得分:1)

这是一种方法。

#include <iostream>
#include <functional>

std::function<double(double)> Deriv( double(*Foo)(double x) )
{
   auto f = [Foo](double x) -> double 
   {
      const double mtDx = 1.0e-6;

      double x1 = Foo(x+mtDx);
      double x0 = Foo(x);

      return ( x1 - x0 ) / mtDx;
   };

   return f;
}

double Foo(double x)
{
   return x*x;
}

double Bar(double x)
{
   return x*x*x;
}

int main()
{
   std::cout << Deriv(Foo)(10) << std::endl;
   std::cout << Deriv(Bar)(10) << std::endl;
}

输出:

20
300

答案 1 :(得分:1)

一旦你可以在一个点计算一个函数的值,你就可以用它来实现你的一般函数。 Lambda表达式允许您轻松生成这些派生函数:

auto MakeDerivative(double (&f)(double)) {
  return [=](double x) { return Deriv(f, x); };
}

如果您希望能够使用有状态函数,则可能需要将Deriv更新为函数模板,其第一个参数类型是模板参数。如果您想重复应用MakeDerivative(因为它的返回类型是有状态闭包),这是正确的:

template <typename F>
double Deriv(F f, double x) {
  // your code here
}

template <typename F>
auto MakeDerivative(F f) {
  return [=](double x) { return Deriv(f, x); };
}

但是,您可能会对&#34;自动差异化等技术感兴趣。它允许你直接用原始函数的定义来表达导数,代价是在一个扩大的域(一个无穷小的邻域,基本上)上工作。

答案 2 :(得分:1)

使用通用lambda,实现玩具derivative很简单。在下面的代码中,derivative是数学意义上的导数运算符。它接受函数double -> double,生成其衍生double -> double

#include <iostream>

double delta = 0.001;

auto derivative = [] ( auto foo ) {
    return [foo] (double x) { 
        // the simplest formula for numeric derivative
        return (foo(x + delta) - foo(x)) / delta;
    };
};

// test
int main() {
    auto quar = [] ( double x ) { return x * x; };
    auto dev_quar = derivative(quar);
    auto dev_dev_quar = derivative(dev_quar);

    for ( double s = 0.0; s < 10.0; ++s ) {
        std::cout << "(" << quar(s) << "," << dev_quar(s) << "," << dev_dev_quar(s) << ")\n";
    }
}