我使用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的方法正好计算多项式,但它并没有正确计算导数。无论我使用什么样的例子,我的教授给我的列表中的系数,这始终是相同的错误。
答案 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;
}