java平方根近似求法,如何通过牛顿法求近似平方根?

这是一篇考拉内部小型技术分享的文章。

这次分享一个求近似平方根的快速方法: 牛顿法。

先上代码:

def sqrt(n):

ret = n

while ret * ret > n:

ret = (ret + n / ret) / 2

return ret

print(sqrt(4))

print(sqrt(2))

代码很简短,很神奇,为什么这样子可以求出来平方根呢?下面来推导一下。

设n的平方根为x, 则有

bbe5b482119eb5a68ebfaff20da70fa5.png, 即

bba9d5d35349607d0e65b679299da972.png, 写成对x的函数的形式为

a1e62b1c845894f6471eefebf5ca2239.png。假设n=4, 我们都知道,4的平方根是2,那用牛顿法怎么求出来呢?先画出来这个函数的图形。

from matplotlib import pyplot as plt

import numpy as np

%matplotlib notebook

xs = np.linspace(-6, 6, 1000)

ys = [x * x - 4 for x in xs]

plt.xlabel('x')

plt.ylabel('y')

plt.plot(xs, [0] * 1000)

plt.plot([0] * 1000, np.linspace(-6, 30, 1000))

plt.plot(xs, ys)

46adf126effcf7993cbe297f49594d3a.png

[]

然后我们取一个点,先取点

105c8729f84eb1e341da31b6eeab0edd.png, 然后做一条切线,它会跟x轴相交于点(2.5, 0), 相同横坐标对应函数上的点为

8a2701d848519f795d5ec2fc2a568ed1.png, 然后我们在x1处再做一条切线,它会和x轴相交于点(2.05, 0), 相同横坐标对应函数上的点为x2(2.05, 0.2025), 继续这样迭代下去,将很快求出来最后x是2.

def f(x):

return x * x - 4

xs = np.linspace(-6, 6, 1000)

ys = [f(x) for x in xs]

plt.xlabel('x')

plt.ylabel('y')

plt.plot(xs, [0] * 1000)

plt.plot([0] * 1000, np.linspace(-6, 30, 1000))

plt.plot(xs, ys)

plt.plot(4, f(4), 'ro')

plt.annotate('x0(4, 12)', (2, 12))

plt.plot([4, 4], [0, 12], '--')

k0 = (f(4 + 0.1) - f(4 - 0.1)) / 0.2

b0 = f(4) - k0 * 4

def f_tangent0(x):

"""

点x0的切线方程

"""

return k0 * x + b0

xs = np.linspace(2, 6, 1000)

ys = [f_tangent0(x) for x in xs]

plt.plot(xs, ys)

plt.plot(2.5, f(2.5), 'ro')

plt.annotate('x1(2.5, 2.25)', (0.5, 5))

plt.plot([2.5, 2.5], [0, 2.25], '--')

k1 = (f(2.5 + 0.1) - f(2.5 - 0.1)) / 0.2

b1 = f(2.5) - k1 * 2.5

def f_tangent1(x):

"""

点x1的切线方程

"""

return k1 * x + b1

xs = np.linspace(1, 6, 1000)

ys = [f_tangent1(x) for x in xs]

plt.plot(xs, ys)

# plt.plot(2.05, f(2.05), 'ro')

# plt.annotate('x1(2.05, 0.2)', (2.05, -5))

452d41172525c9f33a7d3cdcc7b5a07c.png

[]

从图形上可以比较直观的理解牛顿迭代法,但是从代数上怎么进行计算呢?现在来推导一下:

设n的平方根为x, 则有

58cda4785ff0ff1b9fb001ab54e3bd07.png, 即

f29e458becbef85dd211e4716b5ba1f8.png, 写成对x的函数的形式为

554a0dd5a7a9f1af0149df8d9787bb3c.png,我们取一个点

d2ef7efb267cd804891856114b6fa1ca.png, 作一条切线,那么切线的斜率k就是

edaf8b90a245a1e70f9ac0f65b20d94c.png的导数:

3869b7b97d986e3896eec541f5267598.png

由上面的图可以看出来,作x0到x轴的垂线,围成了一个三角形,由三角定理可知:

fac374f2bb9909dab0e6c2aec94c80ad.png

所以有:

ea199089806eb9c442e85432b7f564ec.png

化简得:

0ec88b9a767d96a3899a30e5a1277e6c.png

4a0411f87486a17470565039cd44700f.png

404dbbc1618ceeef5de9f682dad0ff87.png

d5ca72ff9c87d4caeaa1dd1b8d4195e7.png

再看一次代码:

def sqrt(n):

ret = n

while ret * ret > n:

ret = (ret + n / ret) / 2

return ret

一致!

牛顿迭代法求平方根就是这样推导出来的。

其实牛顿法,除了应用在求平方根上,还有很多应用,在机器学习算法的最后优化步骤中,会使用牛顿法求任意函数的最优解,不仅限于

a43355c3e59dab89b6f80d1520e186d4.png这种类型。

建议大家做一下leetcode这道题: sqrtx,会加深理解。

分享内容出自考拉程序猿Hank的blog Hank‘s blog

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值