用递归算法实现开平方根
前言
本文是用手算平方根的解法,用python代码实现,手算平方根方法学自西瓜视频李永乐老师,代码为个人原创。
手算平方根方法
现在我们有一个非负数S,要求S的平方根。我们可以先将S拆成两个数相加,这两个数分别是小于等于S的完全平方数a^2,以及S与这个完全平方数的差b。那么就有等式:S = a^2 + b
然后就可以在这个等式的基础上开始变形了:
移项 : S - a^2 = b
利用平方差公式分解:(√S + a) (√S - a) = b
两边同时除以(√S + a) :√S - a = b / (√S + a)
再移项:√S = a + b / (√S + a)
到这里,右边的√S可以用 a + b / (√S + a)来代替,然后更里面一层又可以再用a + b / (√S + a)代替,一直重复下去,取到的值就越精确。如果上述内容看得不是太懂的话,各位可以去搜一下手算平方根相关的教学视频,网上有很多,讲得都很详细。
代码实现
按照上述手算平方根原理的讲解,我们的代码应该分为两部分。其一是找到那个最靠近S同时又小于等于S的完全平方数,其二是利用被拆开的两个数来递归计算。实际上在上述公式中,任意一个小于S的完全平方数都可以,只不过这个完全平方数越大越靠近S,收敛得就越快。在这里,我是用二分法来找到这个完全平方数的。
def foo(num):
assert num >= 0,"数字太小,不存在平方根"
left,right = 0,num
while left <= right:
middle = (left + right) // 2
if middle ** 2 <= num and (middle + 1) ** 2 > num:
return middle,num - middle ** 2
elif middle ** 2 > num:
right = middle - 1
elif middle ** 2 < num:
left = middle + 1
另外,考虑当S并不是一个完全平方数的时候,上述公式会一直往下嵌套,嵌套的次数越多,得到的值越精确。我们没有必要让它一直计算下去,达到一定的精度就够用了,所以我们需要在递归函数中设置递归次数来强行结束递归。
def fun(a, b, k=5):
if b == 0:
return a
if k == 0:
return a + b / a
return a + (b / (a + fun(a, b, k - 1)))
到这里,我们就已经实现了用递归实行开平方根了,下面把这两个函数结合一下:
def get_SquareRoot(num,k=5):
assert num >= 0,"数字太小,不存在平方根"
left,right = 0,num
a,b = 0,0
while left <= right:
middle = (left + right) // 2
if middle ** 2 <= num and (middle + 1) ** 2 > num:
a,b = middle,num - middle ** 2
break
elif middle ** 2 > num:
right = middle - 1
elif middle ** 2 < num:
left = middle + 1
def func(a, b, k):
if b == 0:
return a
if k == 0:
return a + b / a
return a + (b / (a + func(a, b, k - 1)))
return func(a,b,k)
print(get_SquareRoot(150))
#输出值:12.247448713943559