【问题标题】:Why doesn't this loop terminate?为什么这个循环不终止?
【发布时间】:2010-03-24 03:11:34
【问题描述】:

示例代码如下:

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) 为假,循环将终止。

为什么不会发生这种情况?

【问题讨论】:

  • 这是递归,不是循环。
  • 如果你正确缩进你的代码,就更容易发现这样的逻辑错误

标签: java recursion collatz


【解决方案1】:

因为当你得到 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) ;
}

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

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

【讨论】:

  • 您可以只说else,因为else if 中的条件保证为真。但除此之外,尽管显然不了解 Java,但您还是没问题的。 :-)
  • @Chris:好点子。此外,除了作为练习之外,没有特别的理由递归地实现它。如果语言不进行尾调用优化,那么 while 循环将特别可取。
  • 也许 OP 是从 Scheme 翻译过来的! (不太可能,但还是不得不说。:-P)
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

    问题的答案可以直接在代码中阅读:

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

    【讨论】:

      【解决方案4】:

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

      【讨论】:

      • 对不起,这是作业,简单地给你答案是没有意义的。
      【解决方案5】:

      当输入为 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)
      

      【讨论】:

        【解决方案6】:

        换成这样可以吗?

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

        看起来你得到 2,除以 2 得到 1,然后检查 1/2 是否有余数(确实如此),然后将其乘以 3 并加 1,得到 4... .

        【讨论】:

          【解决方案7】:

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

          只要你得到 1,就会再次执行此代码。

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

          【讨论】:

            【解决方案8】:

            除了else if 来控制n 为奇数的条件外,同一行还需要在条件内添加&amp; n != 1。所以这个:

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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2016-08-22
              • 2015-01-10
              • 2018-10-02
              • 1970-01-01
              • 1970-01-01
              • 2016-03-16
              • 1970-01-01
              相关资源
              最近更新 更多