扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
[问题描述]
有形如:ax3+bx2+cx+d=0这样的一个一元三次方程。给出该方程中各项的系数(a,
b,c,d 均为实数),并约定该方程存在三个不同实根(根的范围在-100至100之间),
且根与根之差的绝对值≥1。
要求由小到大依次在同一行输出这三个实根(根与根之间留有空格),并精确到小数点
后2位。
提示;记方程f(x)=0,若存在2个数x1和x2,且x1 < x2,f(x1)*f(x2) < 0,
则在(x1,x2)之间一定有一个根。
[样例]
输入: 1 -5 -4 20
输出:-2.00 2.00 5.00
问题分析
根据题意,三次方程
二分法:
1. 确定根的区间
考虑在什么样的区间内会有根,由于题目给出了所有的根都在-100到100之间,且根与根之间的差不小于1的限制条件,可知,在[-100,100],[-99,-98],…[99,100],[100,100]这201个区间内,每个区间内至多只能存在一个根,这样除去区间[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或
(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<iostream>
#include<cmath>
using namespace std;
double x[3];
double a,b,c,d,u,v;
int i,t;
double f(double x)
{
double temp;
temp=((a*x+b)*x+c)*x+d;
return temp;
}
int main()
{
while(cin>>a>>b>>c>>d)
{
t=-1;
for(i=-100;i<=100;i++)
{
u=double(i);
v=u+0.99999;
if(fabs(f(u))<0.00001||f(u)*f(v)<=0)
{
t++;
if(fabs(f(u))<0.00001)
x[t]=u;
else
{
while((u+0.001<v)&&fabs(f((u+v)/2))>=0.00001)
{
if(f(u)*f((u+v)/2)<0)
v=(u+v)/2;
else
u=(u+v)/2;
}
x[t]=(u+v)/2;
}
}
}
cout.setf(ios::fixed);
cout.precision(2);
cout<<x[0]<<" "<<x[1]<<" "<<x[2]<<endl;
}
return 0;
}
注意:由于实数运算的误差,判断x是否满足方程f(x)=0应用条件表达式 fabs(f(x))<0.00001来判断,否则将失根。
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者