leetcode--Sqrt算法之原理

目录:

Sqrt算法之原理

起因

  1. 2018/7/8刷leetcode题碰到一题:
  2. 原题:

    实现 int sqrt(int x) 函数。
    计算并返回 x 的平方根,其中 x 是非负整数。        
    由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。
    

自己想法

  1. 通过遍历的方法 相乘
  2. 代码实现:

    def mySqrt(self, x):
            """ :type x: int :rtype: int """
            i=1
            sum=0;
            while True:
                if i*i>x:
                    return i-1
                else:
                    i+=1
  3. 结果:悲剧超时,自己也觉得有非常多的无效计算

百度后

牛顿迭代法

  1. 作用
    并不是所有的方程都有求根公式,或者求根公式很复杂,导致求解困难。利用牛顿法,可以迭代求解。
  2. 请平方根方程式 x^2-a=0 的根
  3. 公式介绍:
    我们每次枚举一个值X0,代入方程看是否为根,不是的话则将X0的值变为:
    X0=X0−F(X0)/F′(X0)
    (其中F′(x) 为 F(x) 的导数)
    其证明过程借用了高数中的基本知识泰勒级数,此处不再赘述。
  4. 应用求平方根

    对于该问题我们可以使用牛顿迭代+高精度除法。 
    我们以开平方根举例 
    对于一个已知的数 a,开根号本质上是求一个X0 使得 X20=a 
    也就是求函数 
    F(x)=x^2−a 的根 
    因为F′(x)=2x
    故每次迭代,x的变化值为: 
    x=x−(x^2−a)/(2x)=(x+a/x)/2 
    
  5. 代码实现:

     def mySqrt(self, x):
                    """ :type x: int :rtype: int """
                    r=x
                    while r*r>x:
                        r=(r+x//r)//2
                    return r
  6. 底层优化
    虽然sqrt() 已经很方便,但确实是存在比其更强大的手写算法,这个黑科技来自游戏雷神之锤3的源代码:(细节见末尾推荐文章)

    int sqrt(float x) { 
        if(x == 0) return 0; 
        float result = x; 
        float xhalf = 0.5f*result; 
        int i = *(int*)&result; 
        i = 0x5f375a86- (i>>1); // what the fuck? 
        result = *(float*)&i; 
        result = result*(1.5f-xhalf*result*result); // Newton step, repeating increases accuracy 
        result = result*(1.5f-xhalf*result*result); 
        return 1.0f/result; 
    }

推荐链接学习

地址:详细sqrt算法解析地址

点赞