您的位置:首页 > 其它

二分法求多项式单根 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)=a​3​​x​3​​+a​2​​x​2​​+a​1​​x+a​0​​在给定区间[a,
b][a,b]内的根。


输入格式:

输入在第1行中顺序给出多项式的4个系数a_3a​3​​、a_2a​2​​、a_1a​1​​、a_0a​0​​,在第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;
}运行结果如下:





由此可见,对于该题来说,递归比循环的执行效率高。这里就要牵涉到递归和循环的执行效率问题了,递归和循环是两种不同的解题思路,一般来说循环的执行效率要比递归高,因为递归可能会有冗余计算,博主的潜意识中也是这样认为的,但是该题给了我当头一棒,到底什么时候用循环,什么时候用递归?坐等大虾们的答复……
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: