求整数的近似平方根(牛顿迭代法)

曾经面试遇到过一道编程题:

给出一个整数,求其近似平方根。

当时没有想到更好的方法,就暴力进行了破解,这当然不会留下好的印象。其实,这道题使用牛顿迭代法可以十分高效的解决。

一、什么是牛顿迭代法

假设有函数:f(x) = 0,要想求出其根,则可以:

  1. 给出一个初始点x0,则在该点的切线为:L: y = f(x0) + {f^'}{(x0)} (x - x0)
  2. 沿着切线方向,与横轴相交,也即令:f(x0) + {f^'}{(x0)} (x - x0) = 0,则求得:x = x0 - f(x0)/ {f^'}{(x0)}
  3. 更新x0,令:x0 = x
  4. 按照1~3步骤迭代下去,直到精度满足要求;

上述算法的第1、2步,其实也就是函数f(x)x0处的泰勒展开取前两项:

f(x) = f(x0) + {f^'}(x0)(x-x0) + {f^''}(x0){(x-x0)^2}/2! + ... + {f^{(n)}}(x0){(x-x0)^n}/n! +R_n(x)

上述泰勒展开式,取前两项并使之等于0,则有:f(x0) + {f^'}(x0)(x-x0),同样可以得到步骤2中的迭代公式。

 

求整数的近似平方根(牛顿迭代法)_第1张图片 牛顿迭代法示意

二、解决求根问题

对于求一个整数近似平方根这个问题,我们可以简单做一个转换,使得问题变为一个方程:x^2 - n = 0。对于方程,n是已知待求平方根的整数,x为我们的求解目标,此时,我们的目的就变成了求解f(x) = x^2-n=0的根了!

那么,利用上述的牛顿迭代法,即可轻松解决。废话少说,直接上码:

def square_root(n:int)->float:
    """ f(x) = x^2 - n = 0,求该方程的根
    """
    x0 = 1
    i = 0
    while True:
        i += 1
        x1 = x0 - (x0**2 - n)/(2*x0)
        if x1 - x0 < 1e-10 and x1-x0> -1e-10:
            print("total iterations: ", i+1)
            break
        x0 = x1
    return x1

代码中:

我们给定初始值为1,这里需要注意的是,我们给的初始值不能是方程的极值点,否则利用牛顿迭代法则无法继续优化下去;

设定了迭代结束条件:|x-x0| < 10^{-10},当满足该条件时,说明求解的精度已经很高了,此时的迭代结果即可作为近似根了。

三、拓展一下

第二部分,给出了使用牛顿迭代法求解给定整数近似平方根的方法,我们同样可以用于处理其他问题,如求解给定整数立方根..n次方根、给定任意方程,求其近似解等问题。

下面给出求解立方根的解法,与求解平方根十分相似,唯一不同之处就在于目标迭代公式稍微发生一点变化:

def cube_root(n:int)->float:
    """ f(x) = x^3 - n = 0,求该方程的根
    """
    x0 = 1
    i = 0
    while True:
        i += 1
        x1 = x0 - (x0**3 - n)/(3*x0**2)
        if x1 - x0 < 1e-20 and x1-x0> -1e-20:
            print("total iterations: ", i+1)
            break
        x0 = x1
    return x1

 

你可能感兴趣的:(优化算法,牛顿迭代法,求平方根,求方程近似根,优化算法,Python)