#include<stdio.h>
#include<math.h>
#include<stdlib.h>
void bisect(float *p,int n,int a);
float value(float *p,int n,int a);
int main()
{
int a,i;
float *p;
printf("enter the degree of the polynomial\n");
scanf("%d",&a);
p=(float *) malloc(a*sizeof(float));
for(i=0;i<=a;i++)
{
printf("enter the coefficient of x^%d\n",i);
scanf("%f",p+i);
}
printf("%f\n",value(p,-2,a));
printf("%f\n",value(p,1,a));
printf("%f\n",value(p,0,a));
for(i=-100;i<100;i++)
{
if(value(p,i,a)*value(p,i+1,a)==0.000)
{
printf("%d\n",value(p,i+1,a));
if(value(p,i,a)==0&&value(p,i+1,a)==0.00)
{
printf("the roots are %d,%d\n",i,i+1);
}
if(value(p,i+1,a)==0.0)
{
printf("the real root is %d\n",i+1);
i++;
continue;
}
}
if(value(p,i,a)*value(p,i+1,a)<0)
{
bisect(p,i,a);
}
}
return 0;
}
float value(float *p,int n,int a)
{
float sum=0.0;
int i;
for(i=0;i<=a;i++)
{
sum=sum+*(p+i)*pow(n,i);
}
return sum;
}
void bisect(float *p,int n,int a)
{
float j,k,l;
int i;
j=n;k=n+1;l=(j+k)/2;
for(i=0;i<50;i++)
{
if(value(p,j,a)*value(p,l,a)==0){break;}
if(value(p,j,a)*value(p,l,a)<0)
{
j=j;k=l;l=(j+k)/2;
}
else if(value(p,l,a)*value(p,k,a)<0)
{
l=(l+k)/2;j=l;
}
}
printf("the root of the equation is %f\n",l);
}
我尝试在main函数中插入print语句,并发现value函数为简单多项式提供了荒谬的结果,但是对于某些多项式,根是正确的,但对于许多多项式来说是错误的。如果算法错误,为什么根会对某些人来说是正确的?
答案 0 :(得分:2)
您的代码中存在很多问题:
main
方法中, printf("%d\n",value(p,-2,a));
编译器应该给你警告:
警告:格式&#39;%d&#39;期望类型&#39; int&#39;的参数,但参数2的类型为&#39; double&#39;
使用%f
代替%d
,value()
返回float
。
malloc
的返回值。应该避免转换malloc
的返回值,因为malloc
返回void *
(这意味着它不需要强制转换)并且转换返回值可以隐藏错误。您可以阅读有关此问题的更多信息here. p = (float *) malloc(a*sizeof(float));
到
p=malloc((a+1) * sizeof *p);
您在这里比较浮动ponit 号码:
if(value(p,i,a)==0&&value(p,i+1,a)==0.00)
不要这样做,请阅读What Every Computer Scientist Should Know About Floating-Point Arithmetic。您可以使用其中一种(例如nearlyEqual())函数。
方法bisect()
:
j=j;k=l;l=(j+k)/2; // j = j, kidding?
答案 1 :(得分:0)
The biggest conceptual or mathematical error (apart from the programming errors explained in the other answer) is that you use integers for the arguments in the value function. It is rarely the case that random polynomials have integer roots. Rename n
to x
for intuitive readability and set the type of x
to float.
Check again your assignment, if the prototype is really value(p,n,a)
, then maybe the intention is that n
is the degree and a
the evalution point, thus the signature should be (*float,int,float)
.
Using this signature, you should really use the Horner scheme to evaluate densely coded polynomials
float value(float *p, int deg, float a) {
int i;
float val = p[deg];
for(i=deg; i-- > 0; ) val = val*a+p[i];
return val;
}
and use descriptive names for variables in the bisection method (instead of j,k,l
usually associated to integers) to avoid mixing them up
float left=a, right = a+1, mid =(left+right)/2;
etc.