【问题标题】:sqrt function weird behaviour in PythonPython中的sqrt函数奇怪的行为
【发布时间】:2012-12-15 21:40:18
【问题描述】:

在 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' 数字,但正如我们在示例中看到的那样,事实并非如此。我也尝试使用不同的增量而不是 1/1024,但它们表现出相似的行为。

如果能说明导致这种行为的幕后情况,我将不胜感激。

【问题讨论】:

  • 1/1024 是 0 它总是为零...这是因为您正在做整数...尝试 1.0/1024
  • 你应该阅读浮点精度。这是一个好的开始:randomascii.wordpress.com/2012/02/25/…
  • Joran,通过“from future import Division”解决
  • 1e309 本身的计算结果为 inf -- 请参阅任何 IEEE-754 规范。
  • 啊,好吧,对不起……你说得对:)

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


【解决方案1】:

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

如果四舍五入,middle_2 &lt; x。现在,如果end - start &gt; delta,你有一个“太低”的无限循环。

如果它被四舍五入,如果是end - start &gt; delta,那么你有一个“太高”的无限循环。

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

【讨论】:

  • 谢谢!我考虑了您的解释,并插入了一些修改,似乎已经解决了问题。在 while 循环中,在进入 if-elif-else 部分之前,我插入了“if middle==start or middle==end: return (start+end)/2”修改,现在它似乎可以工作了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-20
  • 2017-01-14
  • 1970-01-01
  • 1970-01-01
  • 2021-02-21
  • 2013-04-29
相关资源
最近更新 更多