求平方根的多种方法

要求:给出一个整数n,求出n的平方根(返回整数)

Top9 sqrt

直接调用math库(C语言)或者cmath库(C++)里内置的求平方根的sqrt函数即可,最后转化为int类型

int mysqrt(int n){
    return int(sqrt(n));
}

Top8 pow

用内置的pow函数,简单粗暴

int mysqrt(int n){
    return int(pow(n,0.5));
}

Top7 指数恒等式

如果

                                                               x*x=n

我们要求x的值,两边同时取对数,得

                                                        ln(x*x)=lnn

                                                        2lnx=lnn

那么

                                                        lnx=lnn/2

所以

                                                        x=e^(lnn/2)

这里公式凑活着看(不难,是高中知识),主要是我写的latex公式导不过来

代码我们可以直接返回这个值:

int mysqrt(int n){
    return int(exp(log(n) / 2));
}

Top6 精度修正

由于log和exp运算存在精度损失,所以在强制转换为int类型的时候需要加上一个精度(通常是1e-8),把这个精度损失给调整回来

return int(exp(log(n) / 2) + exs);

但是这会导致一个问题,由于引入了浮点数,不同平台的计算结果可能不一样

Top5 暴力枚举

我们从1开始遍历,对于每个数i,如果此时刚有i*i>=n,也就是说(i-1) * (i-1)<n,因此i-1就是所求的平方根

int mysqrt(int n){
    int i=1;
    while(i++){
        if(i*i>=n){
            return i-1;
        }
    }
    return 0;
}

这个方法的缺点是时间复杂度的提高

Top4 二分枚举

我们发现函数n-i*i是一个单调函数,因此我们可以用二分枚举

假设我们要求n的平方根,我们定义一个函数

这里举个例子

显然,我们关注x轴的正方向。随着x的增大,f(x)的值逐渐变小

那么我们要求的n的平方根,即满足f(x)>=0的最大整数x即可

int y(int n,int x){             //计算当前f(x)的值
    return -x*x+n;
}
int binarysqrt(int n){
    int l=0,r=46340;
    int ret=-1;
    while(l<=r){
        int x=(l+r) >> 1;       //除以2我们用移位运算符运算更快
        if(y(n,x) >= 0){
            l = x+1;
            ret = x;
        }
        else{
            r = x-1;
        }
    }
    return ret;
}

这个方法每次只能改变一个位(bit),而且还用到乘法,计算较复杂

Top3 牛顿迭代法

我们定义一个函数

那么我们对于函数上一个点(x,f(x)),找到该点对应的切线,切线交x轴于(x1,0),那么就找到了点(x1,f(x1)),按照同样的方法找到x2x3,……如此循环往复,直到无限逼近这条曲线与x轴的交点就是我们所求的平方根

代码如下:

double func(double x,int n){
    return x*x - n;
}
int mysqrt(int n){
    double x0,x1;
    x1=18                   //这里随便取一个就行
    do{
        x0=x1;
        double v=func(x0,n);
        //切线f'(x) = v + 2x0(x - x0);
        x1=-v/(x0*2)+x0;
    }while(fabs(x0-x1) > 1e-8);
    int ans = (int)(x0+1e-8);
    if(ans*ans>n)
        --ans;
    return ans;
}

牛顿迭代要用到除法更慢了

剩下的2种方法会继续更新,敬请关注!!!

  • 44
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值