sqrt函数在Python中的奇怪行为

时间:2012-12-15 21:40:18

标签: python python-2.7 while-loop sqrt square-root

在Python中,我编写了一个自定义代码sqrt(x,delta)来计算给定数字的平方根,并使用delta-close近似。它使用while循环和类似二进制搜索的算法 代码:

from __future__ import division

def sqrt(x, delta):
    start = 0
    end = x
    while (end-start) > delta:
        middle = (start + end) / 2
        middle_2 = middle * middle
        if middle_2 < x:
            start = middle
            print "too low"
        elif middle_2 > x:
            end = middle
            print "too high"
        else:
            return middle
    result = (start + end) / 2
    return result


它基本上有效且速度很快,但有时会进入无限的循环。
例如:

sqrt(1e27, 1/1024) => works fine (returns 'too low's and 'too high's, then returns correct result)
sqrt(1e28, 1/1024) => works fine
sqrt(1e29, 1/1024) => never-ending loop, it keeps printing 'too low' forever
sqrt(1e30, 1/1024) => works fine
sqrt(1e31, 1/1024) => 'too low' forever
sqrt(1e32, 1/1024) => works fine
sqrt(1e33, 1/1024) => works fine (also surprising after the problem with 1e29 and 1e31)
sqrt(1e34, 1/1024) => works fine
sqrt(1e35, 1/1024) => 'too low' forever
sqrt(1e36, 1/1024) => works fine
sqrt(1e37, 1/1024) => 'too high' forever (too high this time!)
sqrt(1e38, 1/1024) => works fine
sqrt(1e39, 1/1024) => works fine (surprising again..)
... 1e40-1e45 ... they all work fine
sqrt(1e46, 1/1024) => 'too low' forever (surprisingly it occurs now with 1e'even number')
...
sqrt(1e200, 1/1024) => works fine
sqrt(1e201, 1/1024) => works fine
...
sqrt(1e299, 1/1024) => 'too low' forever
sqrt(1e300, 1/1024) => 'too high' forever
...
sqrt(1e304, 1/1024) => 'too high' forever
sqrt(1e305, 1/1024) => works fine
... 305-308 ... they allwork fine
sqrt(1e309, 1/1024) => inf (reached some 'infinite' limit?)

我首先想到的是数字超过限制,比如1e20 ..但是它也适用于它们。此外,我有这个想法是关于1e'odd'或1e'even'数字,但正如我们在示例中看到的那样,并非如此。我也尝试使用不同的delta而不是1/1024,但它们表现出类似的行为。

我会很感激任何解释,告诉我们幕后发生的事情会导致这种行为。

1 个答案:

答案 0 :(得分:4)

float只能代表一组有限的数字。您的代码最终会出现startend是连续两个这样的数字的情况。因此,(start + end) / 2必须向下舍入为start或向上舍入为end

如果它向下舍入,middle_2 < x。现在,如果end - start > delta,您的版本太低了#34}。无限循环。

如果它被四舍五入,如果它被end - start > delta,你就会得到一个太高的&#34;&#34;无限循环。

您应该将delta重新定义为相对错误而不是绝对错误。