C++求解开根号

一般使用两种方法,二分法和牛顿迭代法
一般会让有两种求解结果,一种是求解其整数部分,另一种是求解浮点数并给出精度

二分法

思路
x的平方根的整数部分肯定是在0~x之间的,所以我们可以直接将其转换为在以0开头的有序数组中使用二分查找定位该数字(这数值就是mid:每次二分查找的中间值),那么mid^2一定是最接近x的。

需要定义的变量
l :表示左边值
r:表示右边值
mid:临时存储 l+r /2的中间值

n值的临界条件判断
当mid * mid > x,则 mid 取 l 到 mid -1的中间数,继续循环,直到mid * mid < x,mid就是要找的数 ;
当mid * mid <= x ,则mid取 mid +1 到 r 的中间数,并将mid 赋值给n ,直到两边界限重合,n就是要找的数。

时间复杂度:O(logN)

劣势:数值太大容易超过限制,可以做下修改
将临界的判断条件改成
mid > x / mid,则 mid 取 l 到 mid -1的中间数,继续循环,直到mid < x / mid,mid就是要找的数
当mid <= x / mid ,则mid取 mid +1 到 r 的中间数,并将mid 赋值给n ,直到两边界限重合,n就是要找的数。

    //整数二分
    //边界划分[l, mid - 1] [mid, r]
    int bsqrt(int x)
    {
        if(x == 0||x == 1) return x;
        int r = x;
        int mid = 0;
        int l = 0;
        while(l < r)
        {
            mid = (int)(l/2.0 + r/2.0 + 0.5);//防止超出int范围
            if(mid <= x / mid) l = mid;
            else r = mid - 1;
        }
        return l;
    }

直接浮点数求解二分开根号,注意设置精度

    //使用浮点数二分
    double bsqrt(double x)
    {
        const double esp = 1e-6;//精度
        double r = x, l = 0.0;
        while(r - l > esp)
        {
            double mid = r / 2.0 + l / 2.0;//防止超出范围
            if(mid - x / mid >= esp) r = mid;//防止超出范围
            else l = mid; 
        }
        return l;
    }

牛顿迭代法

来自百度文库

求n的平方根,即计算 x 2 = n x^{2}= n x2=n的解,令 f ( x ) = x 2 − n f(x)=x^{2}-n f(x)=x2n,相当于求解 f ( x ) = 0 f(x)=0 f(x)=0的解。
1.首先取猜测 x 0 x_0 x0(例如可以设初次猜测值为 x / 2 x/2 x/2),如果x_0不是解,做一个经过(x0,f(x0))这个点的切线,与 x x x轴的交点为 x 1 x_1 x1。 同理,如果 x 1 x_1 x1不是解,做一个经过 ( x 1 , f ( x 1 ) ) (x_1,f(x_1)) (x1,f(x1))这个点的切线,与x轴的交点为 x 2 x_2 x2。 以此类推。 以这样的方式得到的xi会无限趋近于f(x)=0的解。

2.判断 x i x_i xi是否是 f ( x ) = 0 f(x)=0 f(x)=0的解有两种方法: 第一种是直接计算 f ( x i ) f(x_i) f(xi)的值判断是否为0,第二种是判断前后解 x i x_i xi x i − 1 x_{i-1} xi1是否无限接近(误差精度)。经过 ( x i , f ( x i ) ) (x_i, f(x_i)) (xi,f(xi))这个点的切线方程为 f ( x ) = f ′ ( x i ) ( x − x i ) + f ( x i ) f(x) = f'(x_i)(x - x_i)+f(x_i) f(x)=f(xi)(xxi)+f(xi) ,其中 f ′ ( x ) f'(x) f(x) f ( x ) f(x) f(x)的导数。(本例中为 2 x 2x 2x)令切线方程等于0,即可求出 x ( i + 1 ) = x i − f ( x i ) / f ′ ( x i ) x(i+1)=x_i - f(x_i) / f'(x_i) x(i+1)=xif(xi)/f(xi)。在此题中,化简可得到迭代公式 x i + 1 = x i − ( x i 2 − n ) / ( 2 x i ) x_{i+1}=x_i - (x_i^{2} - n) / (2x_i) xi+1=xi(xi2n)/(2xi)
在这里插入图片描述
整数部分

#define error 1e-9//误差精度
class Solution {
public:

   //inline double df(int& x, double& x0){return x0 - (x0 * x0 - x)/(2 * x0);}//化简一下(x0 + x / x0) / 2
    inline double df(int& x, double& x0){return (x0 + x/ x0) / 2;}
    int mySqrt(int x)
    {
        if(x == 0 || x == 1) return x;
        double x0 = x / 2.0;
        double x1 = df(x, x0);
        
        while (abs(x0 - x1)  >= error)
        {
            x0 = x1; 
            x1 = df(x, x0);
        }
        return (int) x1;
    }
};

化简下

class Solution {
public:
    int mySqrt(int x) {
    	if(x == 0 || x == 1) return x;
        long res = x;
        while (res * res > x) 
        {
            res = (res + x / res) / 2;
        }
        return res;
    }
};

返回浮点数

#define error 1e-9//误差精度
class Solution {
public:

    //inline double df(int& x, double& x0){return x0 - (x0 * x0 - x)/(2 * x0);}//化简一下x0/2 + x/ (2x0)
    inline double df(int& x, double& x0){return (x0 + x/ x0) / 2;}
    double mySqrt(int x)
    {
        if(x == 0 || x == 1) return x;
        double x0 = x / 2.0;
        double x1 = df(x, x0);
        
        while (abs(x0 - x1)  >= error)
        {
            x0 = x1; 
            x1 = df(x, x0);
        }
        return  x1;
    }
};

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

VoladorL

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值