NOip2001 一元三次方程

一元三次方程,二分法求解,根据题目要求根的范围【-100,100】

考虑在什么样的区间内会有根,由于题目给出了所有的根都在-100到100之间,

且根与根之间的差不小于1的限制条件,可知,

在[-100,-99],[-99,-98],…[99,100],[100,100]这201个区间内,

每个区间内至多只能存在一个根,这样除去区间[100,100],[-100,-100]外,

其他区间[a,a+1],要么f(a)=0,要么f(a)×f(a+1)<0时这个方程在此区间内才有解。

2.求方程的根

确定了方程f(x)=0在区间(a,b)内如果有且只有一个根,那么我们可以有逐步缩小根可能存在的范围的方法确定出某精度下根的数值。本题规定根的精度是0.01,下面采用二分法求区间(a,b)内方程的根,过程如下:

(1)取当前可能存在解的区间(a,b);

(2)若a+0.001>b或 f((a+b)/2)=0,则可确定根为(a+b)/2并退出过程;

(3)若f(a)×f((a+b)/2)<0,则根在区间(a, (a+b)/2)中,

  故对区间(a, (a+b)/2)重复该过程;

(4)若f(a)× f((a+b)/2)>0,则必然有 f((a+b)/2)×f(b)<0,

  也就是说根在((a+b)/2,b)中,应该对此区间重复该过程。 
  
  代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
//本题中特别注意的函数abs(),abs是取整数的绝对值,返回整数值
//fabs()才是用来求浮点数的绝对值,返回浮点数 
float a,b,c,d;
float f(float x) //返回函数值的函数 
{
	return a*x*x*x+b*x*x+c*x+d; 
}
int main(int argc, char *argv[]) {
	float i,x,x1,x2;
	int ans=0;  //用于统计解的个数 
	scanf("%f%f%f%f",&a,&b,&c,&d);
//	printf("%.2f\n",f(-0.5));
	for(i=-100;i<100;i++)
	{
		if(abs(f(i)*f(i+1))==0) //首先判定f(i)=0的解 
		{
		  if(abs(f(i))==0)
		  {
		  	x=i;
		  	ans++;
			printf("%.2f ",x);
		  }	
	    }
		else if(f(i)*f(i+1)<0) //满足解在范围[i,i+1]内的条件 
		{
			x1=i;  
			x2=i+1;
			x=(x1+x2)/2;//若解在[i,i+1]内,采用二分法,查找解 
			while(fabs(f(x))>0.000001&&(x1+0.001)<x2) 
			{  //由于实数运算的误差,判断x是否满足方程f(x)=0
			   //应用条件表达式 fabs(f(x))<0.000001来判断,否则将失根。 
		       //	printf("%.2f\n",f(x));
				if(f(x)*f(x1)>0)//若f(x)*f(x1)>0,则根在[x,x2]范围内 
				{
					x1=x;       //修改根的范围 
					x=(x1+x2)/2;
				//	printf("%.2f %f\n",x,f(x));
				}
				else
				{
					x2=x;       //否则f(x)*f(x1)<=0,则根在[x1,x]范围内 
					x=(x1+x2)/2;
				//	printf("%.2f %f\n",x,f(x));
				}
			}
			ans++;
			printf("%.2f ",x);//输出在[i,i+1]内,使用二分法找到的解 
		}
		if(ans>=3) break;
   	}
	return 0;
}
posted @ 2019-09-05 12:50  颓废の子乃酱  阅读(193)  评论(0编辑  收藏  举报