使用Horner方法在多项式导数函数中的误差在哪里?

时间:2018-03-07 04:50:56

标签: c numerical-methods dev-c++

我使用horners方法创建可以计算多项式的代码,以及它给出的任何系数集的导数。当我有硬编码的值时,Horner的方法工作得很好,但是当我改变我的代码以从命令行提示输入任何输入时,horner的派生开始打印出数十个零的疯狂数字。但仍然正确计算了多项式的horner方法。我并不完全知道此代码中的错误位置。

    #include<stdio.h>
    #include<math.h>
    #include<stdlib.h>

  double horner(double *coeffs, int s, double x)
{
  int i;
  double res = 0.0;

  for(i=s-1; i >= 0; i--)
  {
    res = res * x + coeffs[i];
  }
  return res;
}

double hornerDerivative(double *coeffs, int s_1, double x_1)
{
  int i_1;
  double res_1 = 0.0;

  for(i_1 = s_1; i_1 >= 1; i_1--)
  {
    res_1 = res_1 * x_1 + i_1*coeffs[i_1];
  }
  return res_1;
}

double newton(double *coeffs, double a, double b, double eps)
{
       int N = 0;
       double c = ((a+b)/2);

       while(N < 10)
       {
               double y = horner(coeffs, sizeof(coeffs), c);
               double y_derivative = hornerDerivative(coeffs, sizeof(coeffs), c);
               double c_1 = c - (y/y_derivative);
               printf("c: %f\t",c);
               printf("y: %f\t",y);
               printf("y_der: %f\t",y_derivative);
               printf("c_1: %f\n",c_1);
               if(fabs(c_1-c)<eps)
               {
                    return c_1;                   
               }
               c = c_1;
               N = N + 1;
       }
}

int main(int argc, char **argv)
{
  printf("# of arguments%d\n\n\n\n", argc);
  double coeffs[argc-3];

  double a = atof(argv[argc-2]);
  double b = atof(argv[argc-1]);
  double eps = .001;

  int i;
  for(i=1; i < argc-2; i++)
  {
           coeffs[i-1] = atof(argv[argc-2-i]);
  }

  printf("The root of the equation is: %f\n", newton(coeffs, a, b, eps));
  system("pause");
  return 0;
}

这是我得到的输出。

C:\Dev-Cpp>ProgrammingAssignment1.exe 1 -6 4 12 1 4
# of arguments7



c: 2.500000     y: 0.125000     y_der: 61390858609268995000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000000     c_1: 2.500000
The root of the equation is: 2.500000

正如你所看到的,horner的方法正好计算多项式,但它并没有正确计算导数。无论我使用什么样的例子,我的教授给我的列表中的系数,这始终是相同的错误。

1 个答案:

答案 0 :(得分:1)

如上所述,您的代码中存在一些问题:

  • sizeof的用法。

    • sizeof <array>将返回的字节数
    • sizeof <pointer>将返回系统上指针的大小,通常为4(32位拱形)或8(64位拱形)。

    看看这段代码:

    void foo(int * p)
    {
        printf("sizeof pointer is %z\n", sizeof p);
    }   
    void bar()
    {
        int a[256];
        printf("sizeof array is %z\n", sizeof a);
        foo(a);
    }
    

    它将打印:

    sizeof array is 1024
    sizeof pointer is 8
    

    因此,您无法使用sizeof(coeffs)

  • 当Newton的方法超过10步收敛时,你如何处理?如果从未满足条件fabs(c_1-c)<eps,您应该返回一些值(为什么不提出警告?)

一种解决方案可能是:

#include<stdio.h>
#include<math.h>
#include<stdlib.h>

double horner(double *coeffs, int s, double x)
{
    int i;
    double res = 0.0;

    for(i=s-1; i >= 0; i--)
    {
        res = res * x + coeffs[i];
    }
    return res;
}

double hornerDerivative(double *coeffs, int s_1, double x_1)
{
    int i_1;
    double res_1 = 0.0;

    for(i_1 = s_1; i_1 >= 1; i_1--)
    {
        res_1 = res_1 * x_1 + i_1*coeffs[i_1];
    }
    return res_1;
}

/* New parameter here: cnt the number of elements in coeffs */
double newton(double *coeffs, size_t cnt, double a, double b, double eps)
{
   int N = 0;
   double c = ((a+b)/2);

   while(N < 10)
   {
        /* replacing sizeof... by cnt */
        double y = horner(coeffs, cnt, c);
        /* replacing sizeof... by cnt */
        double y_derivative = hornerDerivative(coeffs, cnt, c);
        double c_1 = c - (y/y_derivative);
        printf("c: %f\t",c);
        printf("y: %f\t",y);
        printf("y_der: %f\t",y_derivative);
        printf("c_1: %f\n",c_1);
        if(fabs(c_1-c)<eps)
        {
            return c_1;                   
        }
        c = c_1;
        N = N + 1;
   }

   /* always return some value */
   fprintf(stderr, "Warning newton do not converge in 10 steps...\n")
   return c;
}

int main(int argc, char **argv)
{
    printf("# of arguments%d\n\n\n\n", argc);
    double coeffs[argc-3];

    double a = atof(argv[argc-2]);
    double b = atof(argv[argc-1]);
    double eps = .001;

    int i;
    for(i=1; i < argc-2; i++)
    {
        coeffs[i-1] = atof(argv[argc-2-i]);
    }

    /* pass the number of elements in coeffs array */
    printf("The root of the equation is: %f\n", newton(coeffs, argc-3, a, b, eps));    
    return 0;
}