Python中的Heron方法

时间:2013-05-17 23:24:21

标签: python-3.x approximation square-root

Heron's method生成一系列数字,表示√n的更好和更好的近似值。序列中的第一个数字是任意猜测;序列中的每个其他数字都使用以下公式从前一个数字 prev 获得:

    (1/2)*(prev+n/prev)

我应该编写一个函数heron(),它将两个数字作为输入: n 错误。该函数应从 1.0 的初始猜测√n开始,然后重复生成更好的近似值,直到连续近似值之间的差值(更确切地说,差值的绝对值)为止最多是错误

    usage:
    >>> heron(4.0, 0.5)
    2.05
    >>> heron(4.0, 0.1)
    2.000609756097561

这有点棘手,但我需要跟踪四个变量:

    # n, error, prev and current

我还需要一个 while循环条件:

    ((current - prev) > error):

while 循环的一般规则是:

    # old current goes into new prev

所以这就是我到目前为止所做的,它并不多,因为一开始我不知道如何在 while 循环下合并'if'语句

def heron(n, error):
    guess = 1
    current = 1
    prev = 0
    while (current - prev) > error:
        previous==1/2*(guess+n/guess):
           print (previous) # just a simple print statement
                            # in order to see what i have so far

请问有人能指出正确的方向吗?

谢谢

5 个答案:

答案 0 :(得分:4)

如果您不想使用生成器,那么最简单的是:

def heron(n, error):
    prev, new = 1.0, 0.5 * (1 + n)
    while abs(new - prev) > error:
        prev, new = new, 0.5 * (new + n/new)
    return new

您还可以生成苍鹭数的“无限”序列:

def heron(n):
    prev = 1.0
    yield prev, float('inf')
    while True:
        new = 0.5 * (prev + n/prev)
        error = new - prev
        yield new, error
        prev = new

现在您可以根据需要打印这么多数字,例如:

list(islice(heron(2), 3))     # First 3 numbers and associated errors

只要误差大于0.01,就生成:

list(takewhile(lambda x:x[1] > 0.01, heron(2)))

答案 1 :(得分:1)

只是建立@ elyase的答案,这里是你如何从他们提供的苍鹭数字生成器获得任意精度平方根。 (生成器只是给出苍鹭序列中的下一个数字)

def heron(n): ### posted by elyase
    a = 1.0
    yield a
    while True:
        a = 0.5 * (a + n/a)
        yield a

def sqrt_heron(n, err):
    g = heron(n)
    prev = g.next()
    current = g.next()
    while( (prev - current) > err):
        prev = current
        current = g.next()
        print current, prev
    return current

print sqrt_heron(169.0,0.1)

除了python语法之外,可能让你搞砸的事情是你需要从初始猜测中计算出两个猜测才能开始,然后你比较这两个猜测的距离。 while条件应该是(prev - current) > err而不是(current - prev) > err,因为我们期望先前的猜测更接近于正方形(因此更大),而不是应该更接近平方根的当前猜测。由于初始猜测可能是任何正数,我们需要从中计算两次迭代,以确保current小于prev

答案 2 :(得分:0)

另一个回答,因为我写这是使用Python生成器函数。我喜欢发电机,但对于这个简单的问题,这些都是过度的。下面是简单while循环的解决方案。

代码下方的评论。 heron0()是你要求的; heron()是我建议的版本。

def heron0(n, error):
    guess = 1.0
    prev = 0.0
    while (guess - prev) > error:
        prev = guess
        guess = 0.5*(guess+n/guess)
        print("DEBUG: New guess: %f" % guess)
    return guess

def _close_enough(guess, n, allowed_error):
    low = n - allowed_error
    high = n + allowed_error
    return low <= guess**2 <= high

def heron(n, allowed_error):
    guess = 1.0
    while not _close_enough(guess, n, allowed_error):
        guess = 0.5*(guess+n/guess)
        print("DEBUG: New guess: %f" % guess)
    return guess

print("Result: %f" % heron0(4, 1e-6))
print("Result: %f" % heron(4, 1e-6))

评论:

  • 您实际上并不需要guesscurrent。您可以使用guess来保留当前猜测。

  • 我不知道您为何要在if循环中放置while语句。首先,它很简单:你只需将其放入,并缩进if下的语句。第二,这个问题不需要它。

  • 检测guess是否接近prev是一件容易又快速的事。但我认为对于数值精确度,最好直接测试平方根guess的实际好坏程度。因此,将guess的值平方并查看它是否接近n。了解在Python中如何测试值是否同时大于或等于较低值以及小于或等于高值是合法的。 (另一种检查方式:abs(n - guess**2) <= allowed_error

  • 在Python 2.x中,如果将整数除以整数,则可能会得到整数结果。因此,1/2很可能会产生0的结果。有几种方法可以解决这个问题,或者您可以在Python 3.x中运行程序,以保证1/2返回0.5,但是为guess创建起始值很简单是一个浮点数。

答案 3 :(得分:0)

我认为这符合您的要求(注意:我使用python 2.7.10编写):它不会假设猜测为1并且需要花费数字#39;和容忍&#39;作为&#39; n&#39;的论据并且&#39;错误&#39;。此外,它没有使用变量&#34; prev&#34;和&#34;当前&#34;或者是一个循环 - 是您的要求的一部分,还是您对解决方案的想法?

def heron(num, guess, tolerance):
    if guess**2 != num:
        ##print "guess =", guess
        if abs(float(num) - float(guess)**2) > float(tolerance):
            avg_guess = 0.5 * (float(guess) + (float(num) / float(guess)))
            return heron(num, avg_guess, tolerance)
        print "Given your tolerance, this is Heron's best guess:", guess
    else:
        print guess, "is correct!"

如果您想查看猜测的进展,请取消注释print cmd。

答案 4 :(得分:0)

由于我对Python的了解非常有限,因此我正在处理相同的问题,而解决该问题的工具并不多。
我想出了这种解决方案,它不是很优雅也不先进,但是它使用Heron算法解决了这个问题。只想在这里分享它:

print("Please enter a positive integer 'x' to find its square root.")
x = int(input("x ="))
g = int(input("What's your best guess: "))
results = [g]
if g * g == x:
    print("Good guess! The square root of", x, "is", g)
else:
    g = (g + (x / g)) / 2
    results.append(g)
    while results[-1] != results[-2]:
        g = (g + (x / g)) / 2
        results.append(g)
    else:
        print(results)
        print("Not quite. The square root of", x, "is", results[-1])