文章目录

  • 一元三次方程的根
    • 1. 题目描述
    • 2. 问题分析与算法设计思路
      • 1)基本思路
      • 2)小心浮点数存储方式的影响
      • 3)如何判断:一个区间是否值得继续搜索
    • 3. 算法实现
    • 4. 运行结果
    • 5. 算法分析

一元三次方程的根

1. 题目描述

有形如:ax3+bx2+cx+d=0ax^3+bx^2+cx+d=0ax3+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)之间一定有一个根。
输入一行,包含四个实数a,b,c,d,相邻两个数之间用单个空格隔开。
输出一行,包含三个实数,为该方程的三个实根,按从小到大顺序排列,相邻两个数之间用单个空格隔开,精确到小数点后2位。
样例输入
1.0 -5.0 -4.0 20.0
样例输出
-2.00 2.00 5.00

2. 问题分析与算法设计思路

1)基本思路

我使用的根的存在定理来解这个问题。对于方程f(x)=0f(x)=0f(x)=0,如果f(x1)∗f(x2)<0f(x_1)*f(x_2)<0f(x1​)∗f(x2​)<0,则在 x1 和 x2 之间至少存在一个实根。注意根的存在定理反过来不一定成立,即f(x1)∗f(x2)>0f(x_1)*f(x_2)>0f(x1​)∗f(x2​)>0不能说明 x1 和 x2 之间就没有根。

利用根的存在定理,我们就可以递归地对指定区间进行二分搜索。通过搜索我们将得到根的近似解。如何确定达到了需要的近似精度呢?

1)区间内有根存在,且区间长度小于指定精度
2)某点处函数值为 0

2)小心浮点数存储方式的影响

注意小数在计算机中存储的是一个近似值,直接判断浮点数相等是不安全的行为。可参考下面的程序代码。我们可以改用判断:

该浮点数与 0 的差的绝对值,是否小于某个微小值(自己设定)

#include<iostream>
using namespace std;
int main(){double a = 0;cout<<"a: "<<a<<endl;if(a == 0) cout<<"yes"<<endl;else cout<<"no"<<endl;a = a + 0.05;a = a - 0.02;a = a - 0.03;cout<<"a: "<<a<<endl;if(a == 0) cout<<"yes"<<endl;else cout<<"no"<<endl;return 0;
}

运行结果

3)如何判断:一个区间是否值得继续搜索

在判断要不要对一个区间进行搜索时,由于根的存在定理的逆命题不成立,我们无法单纯地依靠它进行判断。不过可以设定一个阈值:当区间缩小到某个程度后仍然不能满足根的存在定理时,我们就认为这个区间中将不会有方程的根。

具体的区间阈值大家可以自由选取、多做尝试。我这里使用的是 1 (可能有点草率,但也通过了测试数据)。

3. 算法实现

#include<iostream>
using namespace std;double result[3]={};//存放方程的根
int count=0;//已经找到的方程的根的数量 //前向推导函数值
//bug:之前x的类型使用的int
double fx(double can[4], double x){return can[0]*x*x*x + can[1]*x*x + can[2]*x + can[3];
}//绝对值
double jdz(double x){if(x < 0) x = -x;return x;
} void find_gen(double first, double end, double can[4]){if(count >= 3) return;double mid = (first + end) / 2;double mid_p = 0;double fx1 = fx(can, first);double fx2 = fx(can, end);double fx0 = fx(can, mid);bool cheng = (fx1>0.0001 && fx2>0.0001) || (fx1<0.0001 && fx2<0.0001);if(jdz(fx0) - 0 < 0.0001){result[count++] = mid;mid_p = 0.01;}// printf("first %.4lf, end %.4lf, mid %.4lf\n",first, end, mid);
//  printf("fx1 %.4lf, fx2 %.4lf, cheng %d\n", fx1, fx2, cheng);
//  printf("result: %.4lf, %.4lf, %.4lf\n\n", result[0], result[1], result[2]);//符合根的存在定理说明有根,但不符合并不能说明没有根 if(cheng == 0 || end - first > 1) {if(end - first < 0.01) {result[count++] = mid;return;}find_gen(first, mid - mid_p, can);find_gen(mid + mid_p, end, can);}
}int main(){double can[4] = {};cin>>can[0]>>can[1]>>can[2]>>can[3];//  cout<<"参数:"<<can[0]<<' '<<can[1]<<' '<<can[2]<<' '<<can[3]<<endl;find_gen(-100.0, 100.0, can);cout<<result[0]<<' '<<result[1]<<' '<<result[2]<<endl;return 0;
}

4. 运行结果

5. 算法分析

在对有序数组的搜索中,二分搜索是一种高效的方法。对长度为n的数组的搜索,时间复杂度为:o(log(n))o(log(n))o(log(n))。

与数组的二分搜索的不同之处:

我们通常仅需从数组中找到一个值,因此每次搜索,剩余的搜索空间将变为原来的一半;而一个方程却可以有多个根。在决定是否放弃一个搜索区间时,我没有很合适的判断标准。
因此,前面说的搜索到区间长度小于某个阈值的方法,其实更像是在遍历。只有在某个确定有根存在的、长度已经小于阈值的区间上,才更像是一次二分搜索。

由“递归中的遍历本质”产生的优化方法:

鉴于该递归算法中实际上隐藏着一个遍历阶段,而递归程序本身又是一种时间开销大的写法。其实我们还可以干脆一点:就使用循环遍历+对存在根的小区间二分搜索。有兴趣的小伙伴可以自己尝试一下!

于是,在考虑该算法的时间开销时,可以分为两个阶段:遍历阶段二分阶段

遍历阶段的时间复杂度和初始搜索区间长度以及设定的阈值有关;而二分阶段的时间复杂度和设定的阈值以及要求的结果精度有关。也就是说,输入的规模仅仅是影响算法时间开销的一个因素。因此,时间复杂度的分析超出了我的分析能力,就先不具体分析了叭!

算法 |【实验5.3】:一元三次方程的根-连续区间的二分搜索求近似解相关推荐

  1. 弦截法c语言程序,用弦截法求解一元三次方程的根(利用c语言实现)

    用弦截法求解一元三次方程的根(利用c语言实现)0 特别v2013.09.24浏览296次分享举报 #include #include float f(x) { float a,b,c,d; float ...

  2. python求一元三次方程的根_关于二次、三次、四次方程求解方法讨论

    高次方程求解的一般方法是将高次方程通过配方求解,然后进行次数降解,高次方程转化为容易求解的低次方程. 一元二次方程 求解高次方程,一元二次方程是最为简单的方程.关于一元二次方程 ,通过配方法可以求解: ...

  3. 一元三次方程重根判别式_一元三次方程的根的探究

    1. 因式分解法 因式分解 法不是对所有的三次方程都适用 ,只对一些三次方程适用 .对于大多数 的三次方程, 只有先求出它的根,才能作因式 分解.当然,因式分解的解法 很简便, 直接把三次方 程降次. ...

  4. python迭代法求解方程_第一部分:趣味算法入门;第六题牛顿迭代法求一元三次方程的根...

    100个不同类型的python语言趣味编程题 在求解的过程中培养编程兴趣,拓展编程思维,提高编程能力. 第一部分:趣味算法入门:第六题SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键 ...

  5. python求一元三次方程的根_初中数学专题复习-方程与方程组

    基础知识点: 一.方程有关概念 1.方程:含有未知数的等式叫做方程. 2.方程的解:使方程左右两边的值相等的未知数的值叫方程的解,含有一个未知数的方程的解也叫做方程的根. 3.解方程:求方程的解或方判 ...

  6. python求一元三次方程的根_【九年级 】知识点8 一元二次方程根的判别式的应用...

    知识点8 一元二次方程根的判别式的应用 [题目预览] [视频讲解] [分析点评] 此题考查一元二次方程根的判别式与一元二次方程根的情况,当判别式的值大于0时,方程有两个不相等的实数根,当判别式的值等于 ...

  7. 使用牛顿迭代法求根 一元三次方程的根

    牛顿迭代法(Newton's method)又称为牛顿-拉夫逊方法(Newton-Raphson method),它是牛顿在17 世纪提出的一种在实数域和复数域上近似求解方程的方法.多数方程不存在求根 ...

  8. 算法题(计算一元二次方程的根)

    原题链接 题目描述 求ax^2+bx+c=0方程的根. 输入 T组输入,对于每组输入每行三个实数a.b.c. 输出 对于每一组a.b.c,如果无解就输出"This equation is u ...

  9. python求一元三次方程的根_1.七年级数学:求两车多少小时后相遇?一元一次方程应用题,行程相遇问题...

    欢迎您来到方老师数学课堂,请点击上方蓝色字体,添加关注.所有的视频内容,全部免费,请大家放心关注,放心订阅. 七年级数学:求两车多少小时后相遇?一元一次方程应用题,行程相遇问题.大家先在草稿本上,认真 ...

最新文章

  1. [BZOJ2938]:[Poi2000]病毒
  2. 社交网络图挖掘4--三角形计数问题
  3. 支付宝移动支付文档url
  4. python os.chdir函数
  5. 网络推广方案分享网站想要更快的优化到首页的技巧!
  6. java中是引用传递还是值传递....
  7. java 交互输入_JAVA -----------交互式程序
  8. 项目奖金一般有多少_全年一次性奖金如何进行纳税筹划?
  9. 【今晚七点半】:5G时代的云游戏还缺什么?
  10. oracle pga的作用,浅析Oracle中PGA和UGA两者间的区别
  11. shell之文本过滤(grep)
  12. c#读取mysql返回的值类型_C#中Mysql读取字段值
  13. 《史上最简单的 SpringCloud 教程》系列 (转载 http://blog.csdn.net/forezp/article/details/70148833 本文出自方志朋的博客)
  14. 图像元数据(Metadata) ——Exif信息分析
  15. bzGhost打造跨平台即时聊天软件之专栏介绍
  16. airtest--自动刷喵币
  17. 请总结描述用户和组管理类命令的使用方法并完成以下练习
  18. 如何处理“WLAN没有有效的IP配置”这一问题?
  19. GK_Zone与GK_CM的区别
  20. pcsx2 linux双显卡,PCSX2模拟器下载-PCSX2(PS2模拟器)官方下载-PC下载网

热门文章

  1. linux yum安装mysql及配置
  2. 虚拟化中的链接克隆技术
  3. 你被优衣库遭到******与英特尔漏洞刷屏了吗?
  4. OpenCV—画直角边的直线(粗线)
  5. 解决电脑浏览器打不开网页问题
  6. TencentOS-tiny 时间管理(十 六)- 时间片轮转机制
  7. 使用Arthas排查问题
  8. HTTP HTTPS 创建CA证书
  9. Wireshark捕获过滤器和显示过滤器
  10. esp32 + python 呼吸灯实现