如何使 Python 在 For 循环中第 n 次迭代时打印一些内容?

How to Make Python Print something at nth Iteration within a For Loop?

我想先说明我对 Python 还很陌生,并且只是在研究生院的特定 class 中才开始使用它。

我编写了一个脚本来使用迭代方法(例如不动点法、二分法和牛顿-拉夫逊法)查找函数的根。我的算法的 python 代码如下:

不动点法:

def fixedpoint(func, g_func,x0,tol, MAXIT):
    
    def g(x):
        return eval(g_func)
    
    print(f"Seeking root of {func}.")
    print("FIXED POINT ITERATION:")
    iterated_x = g(x0)
    for i in range(0, MAXIT):
        iterated_x = g(iterated_x)
        print("Iteration", i + 1, iterated_x)
        condition = abs(g(iterated_x) - (iterated_x)) 
        if condition < tol:
            print(f"The root converges to {iterated_x} after {i+1} iterations.")
            break
        if i == MAXIT and condition >= tol:
            print("ERROR: The root did not converge after maximum iterations.")

fixedpoint('x**2 - 4*x + 2', '(x**2+2)/4', 0.75, 10**(-4), 100)
fixedpoint('math.exp(-x) + x - 7 ', '7 - math.exp(-x)', 0.75, 10**(-4), 100)

二分法:

def bisection(func,a, b, tol, MAXIT):
    
    def f(x):
        return eval(func)
    
    print(f"Seeking root of {func}")
    print("BISECTION METHOD:")
    if f(a)*f(b) <0:
        for i in range(0, MAXIT):
            c = (a+b)/2
            if f(a)*f(c) < 0:
                a = a
                b = c
                print(f"Iteration", i + 1, f(c))
            elif f(b)*f(c) < 0:
                b = b
                a = c
                print(f"Iteration", i + 1, f(c))
            if f(c) == 0 or abs(f(c)) < tol:
                print ("Exact Solution Found")
                print(f"Iteration", i + 1, c)
                print("The root converges to", c, "after", i + 1, "iterations.")
                break
            elif i == MAXIT and abs(f(c)) > tol:
                print("Bisection method fails.")
                
    return None

bisection('x**2 - 4*x + 2',0.5, 1, 10**(-4), 100)
bisection('math.exp(-x) + x - 7',6, 8, 10**(-4), 100)

牛顿-拉夫逊法:

def newtonraphson(func, deriv, x0, tol, MAXIT):
    
    def f(x):
        return eval(func)

    def ddx(x):
        return eval(deriv)
        
    
    print(f"Seeking root of {func}.")
    print("NEWTON-RAPHSON METHOD:")
    
    for i in range(1, MAXIT):
        iterated_x = x0 - (f(x0)/ddx(x0))
        x0 = iterated_x
        print(f"Iteration", i, x0)

        if f(x0) < tol:
            print(f"The root converges to {x0} after {i} iterations.")
            break
        elif i==MAXIT and f(x0) > tol:
            print("After maximum iterations, root was not found.")

newtonraphson('x**2-4*x+2', '2*x-4', 0.75,10**(-4), 100)
newtonraphson('math.exp(-x) + x - 7', '-(math.exp(-x)) + 1', 0.75,10**(-4), 100)

虽然我的脚本能够成功找到我感兴趣的方程的根,但我遇到了一个更简单的问题。基本上,我想告诉我的程序,如果在最大迭代后,我的容忍条件没有满足,打印“方法失败”。

但是,当我尝试将最大迭代次数设置为 100 且容差设置为 0.0001 时不覆盖的函数时,我的代码不会打印我想要的语句。

我的语法是否适合 fail print 语句?

像“if i==MAXIT and f(x0) > tol”这样的条件在我编写的函数的上下文中有意义吗?

对于此问题的任何和所有建议,我将不胜感激,因为我正在努力改进 Python。

谢谢。

您面临的问题是 python 中的 range 只能从开始索引到结束索引之前的一个函数。也就是说,range(0,3) 遍历数字 (0,1,2)。您的代码中发生的事情是您无法激活失败条件,因为索引实际上从未达到该值。但是,修复很容易。在你说的函数中:

for i in range(1,MAXIT):
    if f(x0) < tol:
        print(f"The root converges to {x0} after {i} iterations.")
        break
    elif i==MAXIT and f(x0) > tol:
        print("After maximum iterations, root was not found.")

只需将其替换为

for i in range(1,MAXIT):
    if f(x0) < tol:
        print(f"The root converges to {x0} after {i} iterations.")
        return

print("After maximum iterations, root was not found.")

相反。如果找到解决方案,这将停止该功能,如果您设法通过整个循环而没有找到答案,则会向您提供错误消息。

在 Python 中实现此目的的一个好方法是使用 for\else 结构。本质上,如果您将“else”子句挂在 for 循环之外,如果循环由于 break 语句而没有提前终止,它将执行。这对于正在搜索某些东西的循环非常有用,而根查找绝对适合这种模式。所以你的定点迭代循环看起来像:

for i in range(0, MAXIT):
    iterated_x = g(iterated_x)
    condition = abs(g(iterated_x) - (iterated_x)) 
    if condition < tol:
        print(f"The root converges to {iterated_x} after {i+1} iterations.")
        break
else:
    print("ERROR: The root did not converge after maximum iterations.")

这样做的一个好处是,如果您在循环中更改成功标准并不重要——如果您不使用 break 语句声明成功,则 else 子句将运行,无论多么成功定义。