【问题标题】:Return statement does not correctly terminate a recursive methodReturn 语句未正确终止递归方法
【发布时间】:2018-09-10 02:04:32
【问题描述】:

我有一个方法 getNextPrime(int num),它应该识别该方法接收到的值之后最接近的素数。

如果 num 是偶数,它会增加它并再次调用自己。如果它是奇数,它将运行一个 for 循环来检查它是否可以被 3 和 num 的半值之间的奇数整除。如果是,则将 num 增加 2 并且该方法将再次调用自身,否则它将返回新的 num 值,它是一个质数。

问题是,当程序到return语句时,会跳转到if语句,返回num+1的原始值。我调试了一段时间,它只是没有意义。无论我将 return 语句放在哪里,该方法都会跳转到 if 语句,而不是终止该方法并将值返回到调用它的位置。

public int getNextPrime(int num){

    if(num % 2 == 0){
        //even numbers are not prime

        getNextPrime(++num);
    }
    else{

        for(int i = 3; i < (num + 1) / 2; i += 2){

            if(num % i == 0) {
                getNextPrime(num += 2); //consider odd numbers only
            }
        }
    }

    return num; //jumps to if and terminates
}

但是,如果我将 else 语句更改为单独的 if 语句,if(num % 2 != 0) 就可以了。

为什么会这样?

*注意 - 给方法的值大于 3,1、2 和 3 是素数这一事实无关紧要。

【问题讨论】:

  • @JimGarrison 好的,我明白了,这是有道理的。我只是将每个 getNextPrime() 更改为 return getNextPrime() ,现在它可以工作了。谢谢!
  • 我把我的评论变成了答案,如果有帮助请采纳,以便其他人找到解决方案。

标签: java if-statement return primes


【解决方案1】:

当我们使用参数 8 调用您的函数时,让我们尝试查看调用堆栈;

第一个调用是:getNextPrime(8)。由于数字是偶数,该函数进入 if 部分并使用 getNextPrime(9) 再次调用自身。这次 else 部分开始,检查 for 循环中的可分性,发现 9 是可整除的,因此调用 getNextPrime(11)。现在 getNextPrime(11) 再次执行 else 和 for 循环,发现 11 是素数并将数字 11 返回给调用者,但是如果仔细观察,您不会将这个值存储在变量中,num 变量在getNextPrime 调用为 9,当 getNextPrime(9) 返回时,它将该值返回给 getNextPrime(8)。在您的 getNextPrime(8) 中,您也没有真正存储从递归调用堆栈返回的 num 变量。您只需返回该函数中定义的 num 变量,您在调用 getNextPrime(11) 之前碰巧增加了该变量,因此该值为 9,并返回 9。

下面给出了具有相同 if else 块的更正程序供您参考。

public static int genNextPrime(int num) {
    if (num % 2 == 0) {
        num = genNextPrime(++num);
    } else {
        for (int i = 3; i < (num + 1) / 2; i += 2) {
            if (num % i == 0) {
                num += 2;
                num = genNextPrime(num);
            }
        }
    }
    return num;
}

【讨论】:

    【解决方案2】:

    这里只有一个结构性问题。达到单次返回不会折叠整个调用堆栈,它只会返回到上一次调用。

    您需要保存每次调用 getNextPrime() 的结果并将其用作返回值,因此实际找到的值会沿调用链传递回并返回给初始调用者。就目前而言,您只返回传入的数字,因为您从未修改过它。

    修复是一个非常简单的修改。你在哪里

    getNextPrime(++num);
    
    ... and ...
    
    getNextPrime(num+2);
    

    替换它们
    return getNextPrime(++num);
    
    ... and ...
    
    return getNextPrime(num+2);
    

    您选择的算法的问题是它效率低下。您只需要使用较小的素数来测试可除性,而不是所有奇数,并且只能使用原始数字的 平方根

    实施留作练习。

    【讨论】:

    • 谢谢!我没有考虑它的效率,但我实施了它并且它工作得很好。感谢您的提示!
    【解决方案3】:

    您的 return 语句工作正常,但是 ..您已将 1,2 和 3 排除在逻辑之外。 2是偶素数,1不是素数。

    【讨论】:

    • 我省略了 1、2 和 3,因为在这种情况下,将赋予此方法的值总是大于 3。但是,return 语句不起作用。例如,如果我给出值 20,它将返回 21 而不是 23。或者如果我输入 54,它会返回 55 而不是 59。
    猜你喜欢
    • 1970-01-01
    • 2018-07-21
    • 2017-07-28
    • 2016-05-21
    • 1970-01-01
    • 1970-01-01
    • 2020-01-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多