递归地找到二阶导数

时间:2015-02-04 09:31:03

标签: c math recursion calculus derivative

我正在尝试用C编写一个程序,它找到f(x)的二阶导数的数值,其中给出了x。当我使用我的函数找到一阶导数时,一切似乎都运行正常,但递归的二阶导数部分总是给我0.0。这是我的功能:

double derivative(double (*f)(double), double x0, int order) {
    if(order == 1){
        const double delta = 1.0e-6;
        double x1 = x0-delta;
        double x2 = x0+delta;
        double y1 = f(x1);
        double y2 = f(x2);

        return (y2 - y1) / (x2 - x1);
    } else if(order == 2) {
        const double delta = 1.0e-6;
        double x1 = derivative(f, x0, 1)-delta;
        double x2 = derivative(f, x0, 1)+delta;
        double y1 = derivative(f, f(x1), 1)-delta;
        double y2 = derivative(f, f(x2), 1)+delta;

        return (y2 - y1) / (x2 - x1);
    } else {
        printf("order too high error \n");
        return 0;
    }
}

我理解为什么它不能按预期工作 - 在这里我试图通过基于函数f和f'(x)的值导出来找到f的二阶导数。但是我已经在这个问题上工作了好几个小时,我无法想出一个合适的算法来做到这一点。

非常感谢任何帮助。提前谢谢!

3 个答案:

答案 0 :(得分:5)

我将您的代码更改为以下代码,并且按预期工作。

double derivative(double (*f)(double), double x0, int order)
{
         const double delta = 1.0e-6;
         if (order == 1) {
                  double x1 = x0 - delta;
                  double x2 = x0 + delta;
                  double y1 = f(x1);
                  double y2 = f(x2);

                  return (y2 - y1) / (x2 - x1);
          } else if(order == 2) {
                  double x1 = x0 - delta;
                  double x2 = x0 + delta;
                  double y1 = derivative(f, x1, 1);
                  double y2 = derivative(f, x2, 1);

                  return (y2 - y1) / (x2 - x1);
          } else {
                  printf("order too high error \n");
                  return 0;
          }
  }

答案 1 :(得分:2)

我会像这样实现它:

double derivative(double (*f)(double), double x0, int order)
{
         const double delta = 1.0e-6;
         double x1 = x0 - delta;
         double x2 = x0 + delta;
         if (order == 1) {
                  double y1 = f(x1);
                  double y2 = f(x2);

                  return (y2 - y1) / (x2 - x1);
          } else {
                  double y1 = derivative(f, x1, order - 1);
                  double y2 = derivative(f, x2, order - 1);

                  return (y2 - y1) / (x2 - x1);
          }
 }

因为那时不需要“订单太高错误”。

答案 2 :(得分:1)

Parham Alvani已经回答了你的问题并指出了你的功能中的逻辑错误。所以这不是一个真正的答案,只是一些额外的评论。

你可以使函数完全递归,而不必处理除基本情况之外的任何情况:

double derivative(double (*f)(double), double x, int order)
{
    const double eps = 1.0e-3;

    if (order == 0) return f(x);

    double y1 = derivative(f, x - eps, order - 1);
    double y2 = derivative(f, x + eps, order - 1);

    return (y2 - y1) / (2 * eps);
}

对于高阶导数,你最终会多次评估相同的函数值,所以你可以递归地评估导数,并对关系进行硬编码:

  Δf(x) / Δx = (f(x + ε) - f(x - ε)) / (2·ε)
Δ²f(x) / Δx² = (f(x + 2·ε) - 2·f(x) + f(x - 2·ε)) / (4·ε²)
Δ³f(x) / Δx³ = (f(x + 3·ε) - 3·f(x + ε) + 3·f(x - ε) - f(x - 3·ε)) / (8·ε³)

等等。然而,对于高阶导数,选择ε值会变得棘手。当评估的函数值之间的差异很小时,选择它太小会导致错误。