因此,对于赋值,我应该编写一个函数来计算我之前在程序中定义的其他两个函数。如何,我必须定义的下一个函数的复杂性让我感到困惑,我应该如何设置它。基本上,我已经确定我必须写一个while循环,但我无法决定是否有三个不同的条件或if语句来评估这个函数。问题是,循环必须在满足三个条件之一后结束;我现在还不知道如何解决。 这些是三个条件(其中只有一个必须满足才能使循环/函数终止):
这是我目前的代码(显然没有运行):
def newtonsMethod(poly, x_, epislon, timeout):
"""Calculating root of polynomial using newton's Method."""
estimate = 0
epislon = 1e-20
while (abs(evaluatePoly(poly, x_)) < epislon and \
abs(evaluatePoly(findDerivative(poly), x_)) and estimate > timeout):
estimate = x_ - (evaluatePoly(poly) / evaluatePoly(findDerivative(poly)))
x_ = estimate
print(x_)
我应该怎么做?函数名称是赋值的要求,因此无法更改。另外,我是这个东西的完全初学者(刚刚上个月开始),我基本上只需要掌握数据结构,循环和if语句(和函数)。因此,请尽可能保持您的回复简单/虚拟证明。
这是我之前所有与此问题相关的代码:
def findDerivative(poly):
"""Find the derivative of the polynomial and return it as a list of
coefficents"""
count = 0
polyList = []
for nn in poly:
polyList += [nn * count]
count += 1
return polyList[1:]
def evaluatePoly(poly, x_):
"""Evaluates the polynomial at x = x_ and returns the result as a floating-
point number using Horner's rule"""
#http://mathworld.wolfram.com/HornersRule.html
count = 0
polyEval = []
for nn in poly:
xVal = x_**count
polyEval += [xVal * nn]
count += 1
polySum = sum(polyEval)
return float(polySum)
编辑:2016年10月23日
我之前应该已经提到过这一点,或者更详细地解释了赋值,但估计是函数的一个参数,因为它稍后在赋值中作为列表给出。我已经理解超时表示循环在“中断”或结束之前可以运行很多次。该函数返回一个由两部分组成的元组,其中元组的第一个变量是精确的x_值,第二个变量是一个布尔值,表示方法是否成功。使用@Blckknght和@David Bowling的建议,我能够将我的代码改进为以下内容:
def newtonsMethod(poly, x_, epsilon, timeout):
"""Calculating root of polynomial using newton's Method."""
deriv_poly = findDerivative(poly)
deriv = evaluatePoly(deriv_poly, x_)
value = evaluatePoly(poly, x_)
count = 1
while True:
x_ -= value / deriv
if abs(value) < epsilon:
boolean = abs(value) < epsilon
xTuple = (x_, boolean)
return xTuple
if abs(deriv) < epsilon or count > timeout:
boolean = abs(deriv) < epsilon or count > timeout
xTuple = (x_, boolean)
return xTuple
count += 1
但是,当我运行代码时,我仍然遇到崩溃问题。我迟迟没有意识到我不能让两个布尔变量都等于True(对于我的下面的代码,我需要布尔值等于True或False)但是为了使循环停止,其中一个if语句必须等于True。 对于此代码所需的所有混淆和规范,我深表歉意;我希望这个解释有助于理解我的需要。
答案 0 :(得分:0)
正如Barmar所述,使用更简单的while
条件(可能只是while True
)几乎总是比一个甚至不能适合一行的非常复杂的条件更好。你在循环体内的一个或多个if
语句中放置了结束循环的实际逻辑:
while True: # no condition here
# do stuff
if failure_condition1():
break # stop looping
if success_condition():
return result() # another way to stop looping is to return a value
if failure_condition2():
raise SomeException() # you could also raise an exception on failure
# do other stuff
return
,raise
或break
的任意组合可能对您的功能都是正确的,它完全取决于您在满足每个条件时想要做什么(以及您想要的API)是)。
这种循环风格的一个优点是,您可以检查算法中有意义的条件。测试不必在循环的开始处(通常需要您使用在第一次通过条件的组合值来初始化变量)。
以下是我在您的具体问题中应用此类控制流程的方法:
def newtonsMethod(poly, x_, timeout):
"""Calculating root of polynomial using newton's Method."""
estimate = 0
epsilon = 1e-20
deriv_poly = findDerivative(poly)
while True:
value = evaluatePoly(poly, x_)
if abs(value) < epsilon:
return x_
deriv = evaluatePoly(deriv_poly, x_)
if abs(deriv) < epsilon or estimate > timeout:
raise ValueError("Not converging")
#print(x_, value, deriv)
x_ -= value / deriv
estimate += 1
请注意,我们每次传递只需要调用evaluatePoly
两次,因为我们保存结果而不是重新计算结果。
我还修复了代码中的一些错误。我使用estimate
作为计数器,而不是x_
的别名,并且不再将epsilon
作为在函数体中覆盖的参数(您也将其拼写错误为{{1} }})。
答案 1 :(得分:0)
其他人提出的将复杂条件分解为简单陈述的建议非常好。原始条件中的逻辑是错误的,但可以调整为有效。但是你的功能还存在其他问题。
无需在循环之前为epsilon
赋值,因为此值作为函数参数提供。 estimate
应该作为一个计数器运行,但是在下一次迭代中,会混淆地分配用于x_
的值。我在下面的代码中将estimate
重命名为iterations
。
您应该使用:
abs(evaluatePoly(poly, x_)) > epsilon
因为只要在x_
评估的多项式的值大于epsilon
,您就希望循环继续。并且,为了避免在更新x_
的值的语句中出现问题,您希望仅在以下情况下继续循环:
abs(evaluatePoly(findDerivative(poly), x_)) > epsilon
原始代码中有条件丢失。最后,如果iterations
的数量尚未达到timeout
值,您希望继续循环。如果满足上述所有条件,您只想循环,因此您的条件表达式应为:
while abs(evaluatePoly(poly, x_)) > epsilon and \
abs(evaluatePoly(findDerivative(poly), x_)) > epsilon and \
iterations < timeout:
我以两种方式改变了你的下一个作业陈述。首先,现在分配给x_
而不是旧的,混乱的estimate
变量。其次,你错过了evaluatePoly()
函数中的第二个参数。我添加了一行来增加iterations
计数器,并将print()
移出循环,这样您才能看到最终结果。
以下是修改后的代码:
def newtonsMethod(poly, x_, epsilon, timeout):
"""Calculating root of polynomial using newton's Method."""
iterations = 0
while abs(evaluatePoly(poly, x_)) > epsilon and \
abs(evaluatePoly(findDerivative(poly), x_)) > epsilon and \
iterations < timeout:
x_ = x_ - (evaluatePoly(poly, x_) / evaluatePoly(findDerivative(poly), x_))
iterations += 1
print(x_)
以下是使用您提供的findDerivative()
和evaluatePoly()
函数运行的示例:
>>> xpr = [0, 0, 5]
>>> newtonsMethod(xpr, -1, 1e-20, 1000)
-2.91038304567e-11
>>> evaluatePoly(xpr, -2.91038304567e-11)
4.235164736261692e-21
我查看了您发布的新功能定义,并发现了问题。代码中的基本问题是value
和deriv
仅在循环外评估一次。您需要在循环内部移动这两个语句,以便在每次迭代后更新它们。此外,我会将分配移动到x_
到循环结束,以便在更新之前测试您的第一个猜测。您也可以简化if
语句的主体。实际上,当您因deriv
的值不可接受的小值或超时而逃避函数时,您的函数会报告True
。我假设您希望它报告False
。以下是我修改代码的方法:
def newtonsMethod(poly, x_, epsilon, timeout):
"""Calculating root of polynomial using newton's Method."""
deriv_poly = findDerivative(poly)
count = 1
while True:
deriv = evaluatePoly(deriv_poly, x_)
value = evaluatePoly(poly, x_)
if abs(value) < epsilon:
boolean = True
return (x_, boolean)
if abs(deriv) < epsilon or count > timeout:
boolean = False
return (x_, boolean)
x_ -= value / deriv
count += 1
以下是一个示例运行:
>>> xpr = [0, 0, 5]
>>> newtonsMethod(xpr, -1, 1e-20, 1000)
(-2.9103830456733704e-11, True)
>>> evaluatePoly(xpr, -2.9103830456733704e-11)
4.235164736271502e-21
我猜这些结果与早期结果之间的细微差别是由于舍入误差和不同的计算程序。