为什么我的Collat​​z序列代码执行但显示错误?

时间:2019-01-17 13:32:55

标签: python recursion collatz

这是我在Collat​​z序列上的代码:

def collatz(a):
    while (a != 1):

    if a%2 == 0:
        a = a//2
        print (a, " -> ")
        a = collatz(a)
    elif a%2 != 0:
        a = int(3*a + 1)
        print (a, " -> ")
        a = collatz(a)


x = int(input("Enter a number: "))
collatz(x)

我得到的输出对于输入的每个数字都是完美的,但是Jupyter Notebook也显示出某种错误。我在递归中犯了某种错误吗?我已经链接了显示的输出和错误。

https://ibb.co/C1jCthq

1 个答案:

答案 0 :(得分:1)

您执行a = collatz(a),但是由于您的函数没有return语句,因此会将a设置为None。然后,在循环的下一个迭代中,您尝试对a进行算术运算。这将失败,因为您无法对None进行算术运算。

您实际上根本不需要递归。您已经有一个循环,因此您只需删除那些collat​​z调用即可。

def collatz(a):
    while (a != 1):

        if a%2 == 0:
            a = a//2
            print (a, " -> ")
        elif a%2 != 0:
            a = int(3*a + 1)
            print (a, " -> ")


x = int(input("Enter a number: "))
collatz(x)

...但是,如果您对递归不满意,也可以这样做。删除while循环,然后在函数末尾调用collatz

def collatz(a):
    if a == 1:
        return
    if a%2 == 0:
        a = a//2
    elif a%2 != 0:
        a = int(3*a + 1)
    print (a, " -> ")
    collatz(a)

此方法的缺点是,如果函数重复执行999次以上,它将在“超过最大递归深度”的情况下崩溃。 Collat​​z序列很快收敛到1,因此对于特定算法而言,这可能不是一个实际问题,但是在编写任何递归函数时要牢记这一点。


这两种方法都具有在序列的最终编号之后打印“->”的潜在不良行为。在这种“边打印边打印”代码样式中,这是一个相当普遍的问题。一种可能的解决方案是从函数中删除打印调用,而不是返回序列值的列表。然后,您可以根据实际情况设置输出的样式,使用join用箭头插入数字。

def collatz(a):
    result = [a]
    while (a != 1):

        if a%2 == 0:
            a = a//2
        elif a%2 != 0:
            a = int(3*a + 1)
        result.append(a)
    return result

x = int(input("Enter a number: "))
seq = collatz(x)
print(" -> ".join(str(num) for num in seq))