A polynomial of degree n has the common form as p(x)=c
Your task is to write a function to find a root of a given polynomial in a given interval.
Format of function:
double Polynomial_Root(int n, double c[], double a, double b, double EPS);
where int n is the degree of the polynomial; double c[] is an array of n+1 coefficients c
of the given polynomial; double a and b are the two end-points of the given interval; and double EPS is the accuracy of the root.
The function must return the root.
Note: It is guaranteed that a unique real number r exists in the given interval such that p ( r ) = 0.
Sample program of judge:
#include <stdio.h>
#include <math.h>
#define ZERO 1e-13 /* X is considered to be 0 if |X|<ZERO */
#define MAXN 11 /* Max Polynomial Degree + 1 */
double Polynomial_Root(int n, double c[], double a, double b, double EPS);
int main()
{
int n;
double c[MAXN], a, b;
double EPS = 0.00005;
int i;
scanf("%d", &n);
for (i=n; i>=0; i--)
scanf("%lf", &c[i]);
scanf("%lf %lf", &a, &b);
printf("%.4f\n", Polynomial_Root(n, c, a, b, EPS));
return 0;
}
/* Your function will be put here */
Sample Input:
2 1 1.5 -1
0 2
Sample Output:
0.5000
感谢一位大佬。
解法:
用优化牛顿法迭代,具体思路是用
μ
(
x
)
=
f
(
x
)
f
′
(
x
)
\mu(x)=\frac{f(x)}{f'(x)}
μ(x)=f′(x)f(x)代替
f
(
x
)
f(x)
f(x)代入到牛顿法的公式中,原理是
μ
(
x
)
\mu(x)
μ(x)的解和
f
(
x
)
f(x)
f(x)相同,且重根也能算。(将
f
(
x
)
f(x)
f(x)写为
f
(
x
)
=
(
x
−
p
)
m
g
(
x
)
f(x)=(x-p)^mg(x)
f(x)=(x−p)mg(x)很容易验证)
退出条件:牛顿法退出条件。另一篇教程中寻找误差最小的根并不必要。
迭代次数:迭代1000次可过,另一篇教程中区间内代多个值并不必要。
卡点:
测试点 | 卡点 |
---|---|
1点 | 判断区间是否颠倒 |
2,3点 | 优化牛顿法 |
3,5点 | 分子分母都为0(建议不要判断分母是不是0) |
4点 | 输出-0.0000(优化牛顿法不会出现-0.0000输出,建议忽略判断) |
5点 | 根在区间外侧 |
必须做的:
- 优化牛顿算法
- 判断根是否在区间内
不必要做的:
3. 判断分母是否为0
4. 判断根的值是否收敛(所以给了ZERO有什么用呢?)
5. 找误差最小的根
启示:
6. 很多判断其实并不重要,重要的是算法本身
7. 尽信csdn不如无csdn
上代码
double f(int n,double c[],double x){
double ret=0;
for(int i=n;i>=0;i--){
ret=ret*x+c[i];
}
return ret;
}
double f1(int n,double c[],double x){
double ret=0;
for(int i=n;i>=1;i--){
ret=ret*x+c[i]*i;
}
return ret;
}
double f2(int n,double c[],double x){
double ret=0;
for(int i=n;i>=2;i--){
ret=ret*x+c[i]*i*(i-1);
}
return ret;
}
double Polynomial_Root(int n, double c[], double a, double b, double EPS){
if(a>b){
double tem=a;a=b;b=tem;
}
for(double j=0;j<2;j++){
double x=a+(b-a)*j/2;
for(int i=1;i<1000;i++){
double fb=f1(n,c,x)*f1(n,c,x)-f(n,c,x)*f2(n,c,x);
double xn=x-f(n,c,x)*f1(n,c,x)/fb;
if(xn>b||xn<a) break;
if(fabs(x-xn)<EPS){
return xn;
}
x=xn;
}
}
}