Почему мой код последовательности Коллатца выполняется, но показывает ошибку? - PullRequest
0 голосов
/ 17 января 2019

Это мой код последовательности Коллатца:

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 голосов
/ 17 января 2019

Вы делаете a = collatz(a), но, поскольку у вашей функции нет операторов возврата, для a устанавливается значение Нет. Затем в следующей итерации цикла вы попытаетесь выполнить арифметику для a. Это терпит неудачу, потому что вы не можете делать арифметику на None.

Тебе вообще не нужна рекурсия. У вас уже есть цикл, поэтому вы можете просто удалить эти звонки.

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 раз. Последовательности Коллатца сходятся к 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))
...