if语句或while循环条件?

时间:2016-10-22 00:52:46

标签: python function if-statement statements

因此,对于赋值,我应该编写一个函数来计算我之前在程序中定义的其他两个函数。如何,我必须定义的下一个函数的复杂性让我感到困惑,我应该如何设置它。基本上,我已经确定我必须写一个while循环,但我无法决定是否有三个不同的条件或if语句来评估这个函数。问题是,循环必须在满足三个条件之一后结束;我现在还不知道如何解决。 这些是三个条件(其中只有一个必须满足才能使循环/函数终止):

  1. 当前估计的多项式的绝对值小于epsilon,在中 该方法成功的情况如何。
  2. 当前估计的多项式导数的绝对值小于
    比epsilon(这可能导致除以0),在这种情况下方法失败,或
  3. 估计的修订数量超过了超时(估计数不是 融合解决方案)。这个案子也是失败的。
  4. 这是我目前的代码(显然没有运行):

    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。 对于此代码所需的所有混淆和规范,我深表歉意;我希望这个解释有助于理解我的需要。

2 个答案:

答案 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

returnraisebreak的任意组合可能对您的功能都是正确的,它完全取决于您在满足每个条件时想要做什么(以及您想要的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

更新

我查看了您发布的新功能定义,并发现了问题。代码中的基本问题是valuederiv仅在循环外评估一次。您需要在循环内部移动这两个语句,以便在每次迭代后更新它们。此外,我会将分配移动到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

我猜这些结果与早期结果之间的细微差别是由于舍入误差和不同的计算程序。