二分法求多项式单根 PAT
2016-02-29 10:42
543 查看
原题描述如下:
二分法求函数根的原理为:如果连续函数f(x)f(x)在区间[a,
b][a,b]的两个端点取值异号,即f(a)f(b)<0f(a)f(b)<0,则它在这个区间内至少存在1个根rr,即f(r)=0f(r)=0。
二分法的步骤为:
检查区间长度,如果小于给定阈值,则停止,输出区间中点(a+b)/2(a+b)/2;否则
如果f(a)f(b)<0f(a)f(b)<0,则计算中点的值f((a+b)/2)f((a+b)/2);
如果f((a+b)/2)f((a+b)/2)正好为0,则(a+b)/2(a+b)/2就是要求的根;否则
如果f((a+b)/2)f((a+b)/2)与f(a)f(a)同号,则说明根在区间[(a+b)/2,
b][(a+b)/2,b],令a=(a+b)/2a=(a+b)/2,重复循环;
如果f((a+b)/2)f((a+b)/2)与f(b)f(b)同号,则说明根在区间[a,
(a+b)/2][a,(a+b)/2],令b=(a+b)/2b=(a+b)/2,重复循环。
本题目要求编写程序,计算给定3阶多项式f(x)=a_3 x^3 +a_2
x^2 +a_1 x+a_0f(x)=a3x3+a2x2+a1x+a0在给定区间[a,
b][a,b]内的根。
输入在第1行中顺序给出多项式的4个系数a_3a3、a_2a2、a_1a1、a_0a0,在第2行中顺序给出区间端点aa和bb。题目保证多项式在给定区间内存在唯一单根。
在一行中输出该多项式在该区间内的根,精确到小数点后2位。
一开始没有想到用递归来解,而是想到用while循环,也能得出正确的结果,但是出现运行超时的个例,具体代码如下:(可能是哪里有问题,希望各位大虾不吝赐教)
#include <stdio.h>
float a3, a2, a1, a0;
float f(float n)
{
float result;
result = a3 * n * n * n + a2 * n * n + a1 * n + a0;
return result;
}
int main()
{
float a, b, mid, left, right, threshold = 0.001;
scanf("%f%f%f%f", &a3, &a2, &a1, &a0);
scanf("%f%f", &a, &b);
left = a;
right = b;
while (right - left >= threshold && f(left) * f(right) <= 0)
{
if (f(left) == 0)
{
printf("%.2f\n", left);
return 0;
}
if (f(right) == 0)
{
printf("%.2f\n", right);
return 0;
}
mid = (left + right) / 2;
if (f(mid) * f(left) < 0)
right = mid;
else if (f(mid) * f(right) < 0)
left = mid;
}
printf("%.2f\n", (right + left) / 2);
return 0;
}运行结果如下:
![](https://img-blog.csdn.net/20160229105621494?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
<strong style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">出现运行超时现象。</strong>
于是采用递归算法进行解答,得到了正确答案,递归代码如下:
#include <stdio.h>
#include <float.h>
double f(double ratio[], double n)
{
double result;
result = ratio[3] * n * n * n + ratio[2] * n * n + ratio[1] * n + ratio[0];
return result;
}
void GetRoot(double ratio[], double left, double right)
{
double mid, MID, LEFT, RIGHT;
LEFT = f(ratio, left);
RIGHT = f(ratio, right);
mid = (left + right) / 2;
MID = f(ratio, mid);
if (MID > -DBL_EPSILON && MID < DBL_EPSILON)
{
printf("%.2lf\n", mid);
return;
}
else if (MID * LEFT > 0)
{
left = mid;
GetRoot(ratio, left, right);
}
else if(MID * RIGHT > 0)
{
right = mid;
GetRoot(ratio, left, right);
}
}
int main()
{
double ratio[4];
double a, b, mid, left, right, f_left, f_right, f_mid, threshold = 0.001;
scanf("%lf%lf%lf%lf", &ratio[3], &ratio[2], &ratio[1], &ratio[0]);
scanf("%lf%lf", &a, &b);
left = a;
right = b;
GetRoot(ratio, left, right);
return 0;
}运行结果如下:
![](https://img-blog.csdn.net/20160229105958467?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
由此可见,对于该题来说,递归比循环的执行效率高。这里就要牵涉到递归和循环的执行效率问题了,递归和循环是两种不同的解题思路,一般来说循环的执行效率要比递归高,因为递归可能会有冗余计算,博主的潜意识中也是这样认为的,但是该题给了我当头一棒,到底什么时候用循环,什么时候用递归?坐等大虾们的答复……
二分法求函数根的原理为:如果连续函数f(x)f(x)在区间[a,
b][a,b]的两个端点取值异号,即f(a)f(b)<0f(a)f(b)<0,则它在这个区间内至少存在1个根rr,即f(r)=0f(r)=0。
二分法的步骤为:
检查区间长度,如果小于给定阈值,则停止,输出区间中点(a+b)/2(a+b)/2;否则
如果f(a)f(b)<0f(a)f(b)<0,则计算中点的值f((a+b)/2)f((a+b)/2);
如果f((a+b)/2)f((a+b)/2)正好为0,则(a+b)/2(a+b)/2就是要求的根;否则
如果f((a+b)/2)f((a+b)/2)与f(a)f(a)同号,则说明根在区间[(a+b)/2,
b][(a+b)/2,b],令a=(a+b)/2a=(a+b)/2,重复循环;
如果f((a+b)/2)f((a+b)/2)与f(b)f(b)同号,则说明根在区间[a,
(a+b)/2][a,(a+b)/2],令b=(a+b)/2b=(a+b)/2,重复循环。
本题目要求编写程序,计算给定3阶多项式f(x)=a_3 x^3 +a_2
x^2 +a_1 x+a_0f(x)=a3x3+a2x2+a1x+a0在给定区间[a,
b][a,b]内的根。
输入格式:
输入在第1行中顺序给出多项式的4个系数a_3a3、a_2a2、a_1a1、a_0a0,在第2行中顺序给出区间端点aa和bb。题目保证多项式在给定区间内存在唯一单根。
输出格式:
在一行中输出该多项式在该区间内的根,精确到小数点后2位。
输入样例:
3 -1 -3 1 -0.5 0.5
输出样例:
0.33
一开始没有想到用递归来解,而是想到用while循环,也能得出正确的结果,但是出现运行超时的个例,具体代码如下:(可能是哪里有问题,希望各位大虾不吝赐教)
#include <stdio.h>
float a3, a2, a1, a0;
float f(float n)
{
float result;
result = a3 * n * n * n + a2 * n * n + a1 * n + a0;
return result;
}
int main()
{
float a, b, mid, left, right, threshold = 0.001;
scanf("%f%f%f%f", &a3, &a2, &a1, &a0);
scanf("%f%f", &a, &b);
left = a;
right = b;
while (right - left >= threshold && f(left) * f(right) <= 0)
{
if (f(left) == 0)
{
printf("%.2f\n", left);
return 0;
}
if (f(right) == 0)
{
printf("%.2f\n", right);
return 0;
}
mid = (left + right) / 2;
if (f(mid) * f(left) < 0)
right = mid;
else if (f(mid) * f(right) < 0)
left = mid;
}
printf("%.2f\n", (right + left) / 2);
return 0;
}运行结果如下:
<strong style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">出现运行超时现象。</strong>
于是采用递归算法进行解答,得到了正确答案,递归代码如下:
#include <stdio.h>
#include <float.h>
double f(double ratio[], double n)
{
double result;
result = ratio[3] * n * n * n + ratio[2] * n * n + ratio[1] * n + ratio[0];
return result;
}
void GetRoot(double ratio[], double left, double right)
{
double mid, MID, LEFT, RIGHT;
LEFT = f(ratio, left);
RIGHT = f(ratio, right);
mid = (left + right) / 2;
MID = f(ratio, mid);
if (MID > -DBL_EPSILON && MID < DBL_EPSILON)
{
printf("%.2lf\n", mid);
return;
}
else if (MID * LEFT > 0)
{
left = mid;
GetRoot(ratio, left, right);
}
else if(MID * RIGHT > 0)
{
right = mid;
GetRoot(ratio, left, right);
}
}
int main()
{
double ratio[4];
double a, b, mid, left, right, f_left, f_right, f_mid, threshold = 0.001;
scanf("%lf%lf%lf%lf", &ratio[3], &ratio[2], &ratio[1], &ratio[0]);
scanf("%lf%lf", &a, &b);
left = a;
right = b;
GetRoot(ratio, left, right);
return 0;
}运行结果如下:
由此可见,对于该题来说,递归比循环的执行效率高。这里就要牵涉到递归和循环的执行效率问题了,递归和循环是两种不同的解题思路,一般来说循环的执行效率要比递归高,因为递归可能会有冗余计算,博主的潜意识中也是这样认为的,但是该题给了我当头一棒,到底什么时候用循环,什么时候用递归?坐等大虾们的答复……
相关文章推荐
- IIC协议
- SAS NLP Model
- VC++基于微软语音引擎开发语音识别总结
- 软核、硬核以及固核的概念
- js判断是否是用微信浏览器打开
- C#定时器和事件
- HashMap与Hashtable的区别
- android开发框架(二)数据持久化(1)-文件存储
- Android源码之陌陌源码
- mysql 之索引
- iOS开发学习之 - 初识调试(1)
- redis订阅和发布
- BZOJ2038 [2009国家集训队]小Z的袜子(hose)(莫队算法)
- bootsrap判断checkbox选择的个数
- 201601读书分享——《微创新》
- 面向对象的勾勾画画
- BZOJ1061[Noi2008] 志愿者招募
- Android优化——UI优化(五) Listview 重用convertView
- iOS开发文件夹--Copy items if needed
- android 调用系统相机拍照 获取原图