【问题标题】:Finding the square root using Newton's method (errors!)使用牛顿法求平方根(错误!)
【发布时间】:2012-10-02 17:45:18
【问题描述】:

我正在努力完成一个数学问题,该问题使用 Python 中的牛顿猜测和检查方法来近似数字的平方根。用户应该输入一个数字,对该数字的初始猜测,以及他们想要在返回之前检查他们的答案多少次。为了让事情变得更容易并了解 Python(几个月前我才刚刚开始学习这门语言),我将它分解为许多较小的函数;但是,现在的问题是我无法调用每个函数并传递数字。

这是我的代码,有 cmets 帮助(每个函数按使用顺序排列):

# This program approximates the square root of a number (entered by the user)
# using Newton's method (guess-and-check). I started with one long function,
# but after research, have attempted to apply smaller functions on top of each
# other.
# * NEED TO: call functions properly; implement a counting loop so the
# goodGuess function can only be accessed the certain # of times the user
# specifies. Even if the - .001 range isn't reached, it should return.

# sqrtNewt is basically the main, which initiates user input.

def sqrtNewt():
    # c equals a running count initiated at the beginning of the program, to
    # use variable count.
    print("This will approximate the square root of a number, using a guess-and-check process.")
    x = eval(input("Please type in a positive number to find the square root of: "))
    guess = eval(input("Please type in a guess for the square root of the number you entered: "))
    count = eval(input("Please enter how many times would you like this program to improve your initial guess: ")) 
    avg = average(guess, x)
    g, avg = improveG(guess, x)
    final = goodGuess(avg, x)
    guess = square_root(guess, x, count)
    compare(guess, x)


# Average function is called; is the first step that gives an initial average,
# which implements through smaller layers of simple functions stacked on each
# other.
def average(guess, x) :
    return ((guess + x) / 2)

# An improvement function which builds upon the original average function.
def improveG(guess, x) :
    return average(guess, x/guess)

# A function which determines if the difference between guess X guess minus the
# original number results in an absolute vale less than 0.001. Not taking
# absolute values (like if guess times guess was greater than x) might result
# in errors
from math import *
def goodGuess(avg, x) :
    num = abs(avg * avg - x)
    return (num < 0.001)

# A function that, if not satisfied, continues to "tap" other functions for
# better guess outputs. i.e. as long as the guess is not good enough, keep
# improving the guess.
def square_root(guess, x, count) :
    while(not goodGuess(avg, x)):
        c = 0
        c = c + 1
        if (c < count):
            guess = improveG(guess, x)
        elif (c == count):
            return guess
        else :
            pass

# Function is used to check the difference between guess and the sqrt method
# applied to the user input.
import math
def compare(guess, x):
    diff = math.sqrt(x) - guess
    print("The following is the difference between the approximation") 
    print("and the Math.sqrt method, not rounded:", diff)

sqrtNewt()

目前,我收到此错误:g, avg = improveG(guess, x) TypeError: 'float' object is not iterable. 最终函数使用猜测的最终迭代从数学平方根方法中减去,并返回整体差异。 我这样做对吗?如果您可以提供工作代码,我们将不胜感激,并提供建议。再说一次,我是新手,所以对于误解或盲目的明显错误,我深表歉意。

【问题讨论】:

标签: python math newtons-method


【解决方案1】:

牛顿法的实现:

在需要时添加一些小调整应该是相当容易的。试试看,当你遇到困难时告诉我们。

from math import *
def average(a, b):
    return (a + b) / 2.0
def improve(guess, x):
    return average(guess, x/guess)
def good_enough(guess, x):
    d = abs(guess*guess - x)
    return (d < 0.001)
def square_root(guess, x):
    while(not good_enough(guess, x)):
        guess = improve(guess, x)
    return guess
def my_sqrt(x):
    r = square_root(1, x)
    return r

>>> my_sqrt(16)
4.0000006366929393

注意:您会在 SO 或谷歌搜索中找到足够的关于如何在此处使用原始输入的示例,但是,如果您正在计算循环,c=0 必须在循环之外,否则您将陷入无限循环.

quiqk 和脏,有很多改进的方法:

from math import *
def average(a, b):
    return (a + b) / 2.0
def improve(guess, x):
    return average(guess, x/guess)
def square_root(guess, x, c):
    guesscount=0
    while guesscount < c :
        guesscount+=1
        guess = improve(guess, x)
    return guess
def my_sqrt(x,c):
    r = square_root(1, x, c)
    return r

number=int(raw_input('Enter a positive number'))
i_guess=int(raw_input('Enter an initial guess'))
times=int(raw_input('How many times would you like this program to improve your initial guess:'))    
answer=my_sqrt(number,times)

print 'sqrt is approximately ' + str(answer)
print 'difference between your guess and sqrt is ' + str(abs(i_guess-answer))

【讨论】:

  • +1 - 做得很好。我不认为 nic 在此类问题上会给您带来优势。 8)
  • @duffymo -- 是的,是的 :)
  • 感谢根!我应该说我使用的是 Python 3.30 版,所以我进行了相应的更改。我想我也可以从 Math.sqrt 返回的数字中减去猜测。同样,这非常有帮助;非常感谢!
【解决方案2】:

这是一个相当不同的计算平方根的函数;它假设 n 是非负数:

def mySqrt(n):
    if (n == 0):
        return 0
    if (n < 1):
        return mySqrt(n * 4) / 2
    if (4 <= n):
        return mySqrt(n / 4) * 2
    x = (n + 1.0) / 2.0
    x = (x + n/x) / 2.0
    x = (x + n/x) / 2.0
    x = (x + n/x) / 2.0
    x = (x + n/x) / 2.0
    x = (x + n/x) / 2.0
    return x

此算法类似于牛顿的算法,但并不完全相同。它是由一世纪(大约两千多年前)居住在埃及亚历山大港的一位名叫赫伦(他的名字有时拼写为英雄)的希腊数学家发明的。 Heron 的递推公式比 Newton 的简单; Heron 使用 x' = (x + n/x) / 2,而 Newton 使用 x' = x - (x^2 - n) / 2x

第一个测试是零的特殊情况;没有它,(n &lt; 1) 测试会导致无限循环。接下来的两个测试将 n 标准化为范围 1 &lt; n &lt;= 4;缩小范围意味着我们可以很容易地计算出 n 的平方根的初始近似值,这是在 x 的第一次计算中完成的,然后“展开循环” " 并将递归方程迭代固定次数,因此如果两个连续循环之间的差异太大,则无需进行测试和递归。

顺便说一句,Heron 是个很有趣的家伙。除了发明了一种计算平方根的方法之外,他还建造了一个可以工作的喷气发动机、一台投币式自动售货机,以及许多其他巧妙的东西!

您可以在my blog 阅读有关计算平方根的更多信息。

【讨论】:

  • 谢谢!将在我的代码的 cmets 中添加它;很有帮助。
【解决方案3】:

选择的答案有点复杂……没有不尊重 OP。

对于将来使用 Google 搜索的任何人,这是我的解决方案:

def check(x, guess):
    return (abs(guess*guess - x) < 0.001)

def newton(x, guess):
    while not check(x, guess):
        guess = (guess + (x/guess)) / 2.0
    return guess

print newton(16, 1)

【讨论】:

    【解决方案4】:

    我写的不应该那么复杂

    def squareroot(n,x):
    final = (0.5*(x+(n/x)))
    print (final)
    for i in range(0,10):
        final = (0.5*(final+(n/final)))
        print (final)
    

    或者你可以把它改成这样

    n = float(input('What number would you like to squareroot?'))
    x = float(input('Estimate your answer'))
    final = (0.5*(x+(n/x)))
    print (final)
    for i in range(0,10):
        final = (0.5*(final+(n/final)))
        print (final)
    

    【讨论】:

      【解决方案5】:

      您只需要知道序列中的第 n 个项。从莱布尼茨级数,我们知道这是 ((-1)**n)/((2*n)+1)。只需将这个系列对所有 i 求和,初始条件为零即可。

      def myPi(n):
      
      pi=0
      for i in range(0,n):
          pi=pi+((-1)**i)/((2*i)+1)
      return 4*pi
      print (myPi(10000))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-12-09
        • 2014-03-07
        • 2019-06-27
        • 1970-01-01
        • 1970-01-01
        • 2012-10-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多