2010-03-24 5 views
3

Вот пример кода:Почему этот цикл не заканчивается?

public static void col (int n) 
{ 
    if (n % 2 == 0) 
     n = n/2 ; 
    if (n % 2 != 0) 
     n = ((n*3)+1) ; 

    System.out.println (n) ; 
    if (n != 1) 
     col (n) ; 
} 

это прекрасно работает, пока не доберется до 2. Затем она выводит 2 4 2 4 2 4 2 4 2 4 бесконечно. мне кажется, что если 2 введено как n, то (n % 2 == 0) истинно 2 будет разделено на 2 на yeild 1. тогда 1 будет напечатано и с (n != 1) будет ложным, цикл завершится.

Почему этого не происходит?

+1

Это рекурсия, а не петля. –

+1

, если вы правильно отпечатаете свой код, легче обнаружить логические ошибки, подобные этому – Kip

ответ

-1

в дополнение к else if, чтобы регулировать условие, что n нечетно, эта же строка также нуждается в & n != 1, который будет добавлен к нему в условном выражении. Так что это:

else if (n % 2 != 0 & n != 1) 
13

Потому что, когда вы дойдете до 1, вы умножения на 3 и добавления 1, принимая вас 4.

Вам нужен ELSE там. Я не знаю, Java, но это будет выглядеть примерно так:

public static void col (int n) 
{ 
    if (n % 2 == 0) 
     n = n/2 ; 
    else if (n % 2 != 0) 
     n = ((n*3)+1) ; 

    System.out.println (n) ; 
    if (n != 1) 
     col (n) ; 
} 

EDIT: как уже упоминалось в комментариях, вы можете опустить, если тест после того, как еще:

if (n % 2 == 0) 
    n = n/2 ; 
else 
    n = ((n*3)+1) ; 
+5

Вы можете просто сказать 'else', так как условие в' else if' гарантировано будет истинным. Но в остальном вы все поняли, несмотря на то, что, по-видимому, не знали Java. :-) –

+0

@ Крис: Хорошая точка. Кроме того, нет особых причин для реализации этого рекурсивно, кроме как упражнения. Цикл while будет особенно предпочтительным, если язык не выполняет оптимизацию хвостовых вызовов. –

+0

Может быть, OP перевел его с Схемы! (Вряд ли, но должен был сказать это в любом случае. :-P) –

0

использования, если/то/другое. Ваша логика ошибочна.

+1

Это не очень полезно – David

+0

извините, но это домашнее задание, и было бы бессмысленно просто дать вам ответ. –

2

Я думаю, вы должны изменить 2-ое if заявление на else

if (n % 2 == 0)  // if the n is even 
    n = n/2 ; 
else     // if n is odd 
    n = ((n*3)+1) ; 
0

когда вход 2:

if (n % 2 == 0)   //true 
    n = n/2;    //n = 1 
if (n % 2 != 0)   //true 
    n = ((n*3)+1);  //n = 4 

System.out.println (n); //prints 4 
if (n != 1)    //true 
    col (n);    //call col(4) 
0

ли работа, если вы измените его на это?

if (n % 2 == 0) 
    n = n/2 ; 
else if (n % 2 != 0) 
    n = ((n*3)+1) ; 

Похоже, вы получаете 2, разделив на 2, чтобы получить 1, а затем проверить, чтобы увидеть, если 1/2 имеет остаток (он делает), и умножив его на 3 и добавления 1, чтобы получить 4 ....

1

ответ на этот вопрос можно прочитать непосредственно в коде:

Assume n is 2 
(n % 2 == 0) is true therefore n <- 1 
(n % 2 != 0) is also true therefore 4 <- n 

this warrants a call to function with n = 4, which is then changed to 2 and 
"back to square 1" 

путем замены второй тест на еще, вы решить эту логическую проблему, по стоимости возможно, вызвав большую рекурсию (поскольку в текущей логике две операции иногда выполненных на одной итерации). Такое исправление будет также решить более тонкую ошибку, которая заключается в том, что в текущей версии распечатываются не все новые значения n.

Теперь, для дополнительного кредита, докажите, что не имеет значения начального значения n, число рекурсий конечно (т. Е. Последовательность сходится к 1). ;-)

0

если (! П% 2 = 0) п = ((п * 3) +1);

этот код снова реализуется всякий раз, когда вы получаете 1.

поэтому рекурсивная функция будет вызываться многократно, что приведет к бесконечному вызову rec, и код никогда не завершится.

Смежные вопросы