为什么这个循环没有终止?

时间:2010-03-24 03:11:35

标签: java recursion collatz

以下是示例代码:

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得到1,那么将打印1,因为(n != 1)为假,循环将终止。

为什么不发生这种情况?

8 个答案:

答案 0 :(得分: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) ;
}

编辑:如评论中所述,您可以在else之后省略if测试:

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

答案 1 :(得分:2)

我认为您必须将第二个if语句更改为else

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

答案 2 :(得分: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"

通过用else 替换第二个测试,解决了这个逻辑问题,代价是可能导致更多的递归(因为在当前逻辑中,有时在一次迭代中执行两个操作)。这样的修复将也解决一个更微妙的错误,这是在当前版本中并非打印出所有新的n值。

现在,为了额外的功劳,证明无论n的初始值无关,递归的数量是有限的(即,序列收敛到1)。 ; - )

答案 3 :(得分:0)

使用if / then / else。你的逻辑错了。

答案 4 :(得分: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)

答案 5 :(得分: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 ......

答案 6 :(得分:0)

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

只要你得到1,这个代码就会再次实现。

因此将重复调用递归函数,从而导致无限的rec调用,代码永远不会终止。

答案 7 :(得分:-1)

除了else if以管理n是奇数的条件,同一行还需要在条件内添加& n != 1。所以这个:

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