我有一个方法 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是素数的事实并不重要。
答案 0 :(得分:1)
这里只有一个结构问题。到达单个返回不会折叠整个调用堆栈,它只返回到先前的调用。
每次都需要保存调用getNextPrime()的结果并将其用作返回值,因此实际找到的值会沿着调用链传回并返回给初始调用者。就目前而言,您只返回传入的数字,因为您从未修改它。
修复是一个非常简单的修改。你在哪里
getNextPrime(++num);
... and ...
getNextPrime(num+2);
用
替换它们return getNextPrime(++num);
... and ...
return getNextPrime(num+2);
您选择的算法存在的问题是效率低下。您需要仅使用较小的素数来测试可分性,而不是所有奇数,并且只能使用原始数字的平方根。
实施留作练习。
答案 1 :(得分:0)
您需要退出递归循环并在找到素数后立即返回该数字。有一件事你可以尝试Jim建议的解决方案,如果你得到相同的素数,如果最初用素数调用递归方法,你可以做以下几点来防止:
int num = 11;
int nextPrime = getNextPrime (num);
nextPrime = (nextPrime == num) ? getNextPrime (num + 1) : nextPrime;
另一种(有点脏)的方法是在找到素数时设置一个标志,然后阻止执行除return语句之外的任何其他代码。像这样:
static boolean primeFound = false;
public static int getNextPrime(int num) {
if (!primeFound) {
// incrementing num here to prevent returning the same number
// if this method was initially called with a prime number
num += 1;
if (num % 2 == 0 && num != 2) {
return getNextPrime(num);
}
for (int i = 3; i < (num / 2) + 1; i += 2) {
if (num % i == 0) {
return getNextPrime(num);
}
}
primeFound = true;
}
return num;
}
答案 2 :(得分:0)
让我们在使用参数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;
}
答案 3 :(得分:-1)
你的return语句工作正常,但是你已经离开了你的逻辑中的1,2和3。 2是偶数素数,1不是素数。