python中的平方根,牛顿和递归问题

时间:2015-04-07 23:37:31

标签: python algorithm recursion

我正在尝试使用牛顿算法对某个数字的平方根进行近似编程,但是当它为根数为整数的数字进行编程时,它只会因其他所有内容而失败。每次我尝试计算2.25或3或更高的平方时,我都会遇到运行时错误。我该如何解决这个问题?

n = float(input("Which number's square root would you want to compute?  "))

def oldguess():
    root = n /2
    return root

def newguess():
    root = 0.5 * (oldguess() + n / oldguess())
    if root**2 == n:
        print root
        return root
    else:
        newguess()


newguess()

3 个答案:

答案 0 :(得分:0)

因为浮点数如何工作1.23 ** 2永远不会等于你想要的......你需要检查一个阈值

threshold = 1e-5
if abs(root**2 - n) < threshold :

但这似乎不是牛顿法...这是你应该如何根据http://en.wikipedia.org/wiki/Newton%27s_method#Square_root_of_a_number实现它

实际上你应该将先前的猜测与当前的猜测(或当前的猜测)进行比较......因为它总是收敛到一个解决方案,它会在每次迭代时继续接近解决方案(快速,即先前猜测和之间的差异)当前的猜测会迅速接近零)....

所以我会像这样实现它

import random
def newton_squareroot(target,guess=None):
    if guess is None:
        guess = random.randint(1,int(target))
    threshold = 1e-5
    next_guess =  guess - (guess**2-target)/float(2*guess)
    if  abs(guess-next_guess)< threshold:
        return next_guess
    return newton_squareroot( target,next_guess)



print newton_squareroot(2.5)

答案 1 :(得分:0)

@ Joran-Beasly建议,不要使用硬编码阈值,最好保持循环,直到近似值无法改善。

答案 2 :(得分:0)

你的方法实际上不是递归,递归意味着你在一个方法中调用相同的方法并且重用它的结果,或者传递属性以便下次调用适用于前一个。在你的方法中:

def newguess():
    root = 0.5 * (oldguess() + n / oldguess()) #oldguess remains the same, so nothing incremental, every guess will be as bad as the previous one
    if root**2 == n:
        print root
        return root
    else:
        newguess()

您致电oldguess(),因此对newguess()的每次通话都将完全相同:没有“增量行为”。

你可以做的是从一个简单的猜测开始 - 例如将其作为属性传递,然后继续改进猜测:

def newguess(guess,n):
    threshold = 1e-5
    root = 0.5 * (guess + n / guess)
    if abs(root**2-n) < threshold:
        return root
    else:
        return newguess(root,n) #reuse the previous guess and return

print newguess(oldguess(n),n)

使用@JoranBeasley所描述的容忍机制。

还有一个更好地使用oldguess的参数:

def oldguess(n):
    root = n /2
    return root

通常使用全局变量是一个坏主意,对于print结果, I / O (如inputprint的方法不应该是相同的由实用方法处理。

所以完整的代码是:

def oldguess(n):
    root = n /2
    return root

def newguess(guess,n) :
    threshold = 1e-5
    root = 0.5 * (guess + n / guess)
    if abs(root**2 - n) < threshold :
        return root
    else :
        return newguess(root,n) #reuse the previous guess

n = float(input("Which number's square root would you want to compute?  "  ))
print(newguess(oldguess(n),n))