第一个函数是一个天真的二进制搜索实现,用于查找数字的平方根:
def sqrt1(x):
if x < 0:
raise ValueError(x)
if x > 0:
if x < 1:
root = 1
while root ** 2 > x:
root /= 2
half = root
while root ** 2 != x:
half /= 2
diff = root + half
if diff == root:
return root
if diff ** 2 <= x:
root = diff
return root
if x > 1:
root = 1
while root ** 2 < x:
root *= 2
half = root / 2
while root ** 2 != x:
half /= 2
diff = root - half
if diff == root:
return root
if diff ** 2 >= x:
root = diff
return root
return 1
return 0
第二个功能做同样的事情但更简单,比第一个快15倍:
def sqrt2(z):
assert z > 0
x, y = z, None
while x != y:
y = x
x = (x + z / x) / 2
return x
sqrt2
比sqrt1
快得多?sqrt1
更像sqrt2
?答案 0 :(得分:4)
算法1进行二分查找。因此,如果您正在寻找2的平方根,则每次迭代后都会得到以下结果:
1.0 1.0 1.25 1.375 1.375 1.40625 1.40625 1.4140625 1.4140625 1.4140625 1.4140625 1.4140625 1.4140625 1.4141845703125 1.4141845703125 1.4141845703125 1.4141998291015625 1.41420745849609375
我们运行了17次迭代,我们有6位正确的数字:1.41421。经过另外17次迭代后,我们可能会有大约12个正确的数字。在第34次迭代中,我们得到:
1.4142135623260401189327239990234375
这里的正确数字是1.414213562,所以只有10位数。
第二种方法是牛顿方法,它具有二次收敛性。这意味着每次迭代得到两倍的数字,所以你会得到:
0 2.0 1 1.5 2 1.41666666666666666666666666666666666666666666666666666666667 5 1.41421568627450980392156862745098039215686274509803921568627 12 1.41421356237468991062629557889013491011655962211574404458491 24 1.41421356237309504880168962350253024361498192577619742849829 49 1.41421356237309504880168872420969807856967187537723400156101 60+ 1.41421356237309504880168872420969807856967187537694807317668
左栏显示正确的数字位数 - 注意它是如何以指数方式增长的。我在这里切断了输出,因为经过7次迭代后,结果与我选择的精度一致。 (这实际上是以比Python的float
更高的精度数据类型运行,它不能给你60位精度。)
没有。如果你加快速度,它就不可能被称为二进制搜索了。