问题描述 有形如:ax3+bx2+cx+d=0 这样的一个一元三次方程。给出该方程中各项的系数
(a,b,c,d 均为实数),并约定该方程存在三个不同实根(根的范围在-100至100之间),
且根与根之差的绝对值>=1。
要求由小到大依次在同一行输出这三个实根(根与根之间留有空格),并精确到小数点后5位。
提示:记方程f(x)=0,若存在2个数x1和x2,且x1<x2,f(x1)*(x2)<0,则在(x1,x2)之间一定有一个根。
样例
输入:1 -5 -4 20
输出:-2.00 2.00 5.00
分析:由题意知(i,i+1)中若有根,则只有一个根,我们枚举根的值域中的每一个整数x(-100≤x≤100),设定搜索区间[x1,x2],其中x1=x,x2=x+1。若:
⑴f(x1)=0,则确定x1为f(x)的根;
⑵f(x1)*f(x2)<0,则确定根x在区间[x1,x2]内。
⑶f(x1)*f(x2)>0,则确定根x不在区间[x1,x2]内,设定[x2,x2+1]为下一个搜索区间;
若确定根x在区间[x1,x2]内,采用二分法,将区间[x1,x2]分成左右两个子区间:
左子区间[x1,x]和右子区间[x,x2](其中x=(x1+x2)/2)。如果f(x1)*f(x)≤0,
则确定根在左区间[x1,x]内,将x设为该区间的右界值(x2=x),继续对左区间进行对分;
否则确定根在右区间[x,x2]内,将x设为该区间的左界值(x1=x),继续对右区间进行对分;
上述对分过程一直进行到区间的间距满足精度要求为止(即x2-x1<0.000005)。此时确定x1为f(x)的根。
#include <iostream>
#include <time.h>
using namespace std;
const double e=0.00001;
//函数 f(x)=x3-5x2-4x+20
double fx(double x)
{
double x2=x*x;
double x3=x2*x;
return x3-5*x2-4*x+20;
}
//解方程
void findx()
{
double x[10]={0};
int k=0,m=0;
double low,high;
for(int i=-10;i<10;i++)
{
low=i;
high=i+1;
//对每个区间进行求解
while(high-low>e)
{
double mid=(low+high)/2;
if(fx(low)*fx(mid)<=0)
high=mid;
else if(fx(mid)*fx(high)<=0)
low=mid;
else//此区间无解
break;
}
if(high-low<=0.01)//找到了一个解
{
x[k++]=low;
}
if (k > 1 && abs(x[k-1] - x[k-2]) < e)//消除重复的解
k--;
}
for(int i=0;i<3;i++)
cout<<x[i]<<endl;
}
void main()
{
findx();
system("pause");
}