有人可以解释以下功能之间的速度差异吗?

时间:2012-11-15 22:45:46

标签: python case-study

第一个函数是一个天真的二进制搜索实现,用于查找数字的平方根:

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
  1. 为什么sqrt2sqrt1快得多?
  2. 可以使sqrt1更像sqrt2

1 个答案:

答案 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位精度。)

是否可以更快地进行二进制搜索?

没有。如果你加快速度,它就不可能被称为二进制搜索了。