不调用库函数求根号x的计算方法(二分/三分/牛顿迭代法)

求:y=√x

1.二分法求零点

由于函数在(0,+oo)为单调函数,取值为正

y*y - x = 0 设 g(y) = y*y - x ,函数值在自变量y属于(0,+oo)也单调。g(0)<=0 ,g(x+1)>0 所以可在区间[0,x+1]上采用二分法

#include
const double eps=1e-10;//精度小数点后10位
//求y=根号x
//则y^2=x
double Abs(double val) {//求val的绝对值
    if (val < 0)
        val = -val;
    return val;
}
int main(void) {
    double x;
    scanf("%lf", &x);
    double l = 0, r = x + 1, mid = l;
    while (Abs(r - l) > eps) {//区间长度大于eps就继续二分区间
        mid = (l + r) / 2;
        if (mid * mid > x)
            r = mid;
        else
            l = mid;
    }
    printf("%.20f", mid);
    return 0;
}

二分法的时间复杂度为 log2(x/精度)

eg.

输入:2
输出:1.41421356229693630000

 

2.三分法求极值

求√a,需构造函数。由于 a+b>=2√(ab) [当且仅当a等于b时,原式取等]。所以构造函数:

y = x+a/x (a>0)

只有当x=√a时,y可取得极小值。然后三分区间 ( 0, a + 1],当函数求得极值时即求得横坐标 ans = x

#include
const double eps=1e-10;//精度小数点后10位
double Abs(double val) {//求val的绝对值
    if (val < 0)
        val = -val;
    return val;
}
double func(double a, double x){//构造的函数,在(0,+oo)上有唯一的极值
    return x+a/x;
}
int main(void) {
    double x;
    scanf("%lf", &x);
    double l = eps, r = x + 1, lm, rm;
    while (Abs(r - l) > eps) {
        lm = (l*2+r)/3;
        rm = (r*2+l)/3;
        double fl = func(x,lm);
        double fr = func(x, rm);
        if(fl

三分法的时间复杂度为 log1.5 (x/精度)

eg.

输入:2
输出:1.41421357309081250000

 

3.牛顿迭代法 (学过数学的真nb)

//推荐  https://blog.csdn.net/xdu_pyl/article/details/46786167

f(x) = 0

利用泰勒公式,在x0处展开到一阶,即f(x) = f(x0)+f'(x0)*(x-x0) + 误差

设g(x) = f(x0)+f'(x0)*(x-x0) 即f(x)在点x0处的切线

令g(x)=0,解上式得 x = x0 - f(x0)/f'(x0)  设x1 = x

f(x1)比f(x0) 更接近f(x), 得递推式 x[n+1]=x[n] - f(x[n])/f'(x[n])

--

设f(x)=x*x-a=0

则递推式为 x[n+1] = x[n] - (x[n]*x[n]-a)/(2*x[n]) 即 x[n+1] = x[n]/2+a/(2*x[n])

#include
const int N=100;
int main(void) {
    double a;
    scanf("%lf", &a);
    double xn=1;
    for(int i=0;i

牛顿迭代法的时间复杂度 可以取决于迭代次数,一般收敛得很快

输入:2
输出:1.41421356237309490000

 

比较:

二分法:2  输出:1.41421356229693630000

三分法:2  输出:1.41421357309081250000

牛顿法:2  输出:1.41421356237309490000

                   输出:1.41421356237309504880..

 

二分法:102365789  输出: 10117.59798568808400000000

三分法:102365789  输出: 10117.59819612991900000000

牛顿法:102365789  输出: 10117.59798568810600000000

                                  输出: 10117.59798568810501243327

 

结论:

在浮点数运算有误差的情况下,三分法效果最差,二分法适中,牛顿迭代法最精确且时间复杂度低,编程难度最小

你可能感兴趣的:(数值计算)