为什么这个循环不终止?

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的时候能够正常工作,但当n等于2时,它会无限输出“2 4 2 4 2 4 2 4 2 4”。我认为如果n等于2,则(n % 2 == 0)条件成立,2将被2整除得1,然后打印出1,由于(n != 1)条件不成立,循环将终止。为什么不是这样呢?

1
这是递归,不是循环。 - Kevin Crowell
1
如果您正确缩进代码,就更容易发现像这样的逻辑错误。 - Kip
8个回答

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) ;

5
既然在 else if 中的条件肯定为真,你可以只使用 else。不过除此之外,尽管你显然不懂 Java,但你已经全部正确了,:-) - C. K. Young
@Chris:说得好。此外,除了作为练习之外,没有特别的理由要以递归方式实现这个功能。如果语言不执行尾调用优化,则使用while循环会更好。 - Igby Largeman
也许原帖是从Scheme翻译过来的!(虽然不太可能,但还是得说一下。:-P) - C. K. Young

2

我认为你需要将第二个 if 语句改为 else

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

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)。 ;-)


0
请使用if/then/else语句,您的逻辑是错误的。

抱歉,但这是作业,简单地给你答案是没有意义的。 - President James K. Polk

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...


0

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

每当你得到1时,此代码将再次实现。

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


-1

除了使用else if来控制n为奇数的条件外,同一行还需要在条件语句中添加& n != 1。因此,代码应该是这样的:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接