简体   繁体   中英

Return statement does not correctly terminate a recursive method

I have a method getNextPrime(int num) which is supposed to identify the closest prime number after the value received by the method.

If num is even, it will increment it and call itself again. If it is odd, it will run a for loop to check if it is divisible by odd numbers between 3 and num 's half value. If it is then it will increase num by 2 and the method will call itself again, otherwise it will return the new num value which is a prime number.

The problem is, when the program gets to the return statement, it will jump to the if statement and return the original value of num + 1. I have been debugging this for a while and it just doesn't make sense. Wherever I place the return statement, the method just jumps to the if statement instead of terminating the method and returning the value to where it is being called from.

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
}

However, if I change the else statement to a separate if statement, if(num % 2 != 0) it works.

Why does this happen?

*Note - the values given to the method are greater than 3, the fact that 1, 2, and 3 are primes doesn't matter.

There is only one structural problem here. Reaching a single return does not collapse the entire call stack, it only returns to the previous invocation.

You need to save the result of calling getNextPrime() every time and use that as the return value, so the value actually found gets passed back along the call chain and returned to the initial caller. As it stands you return only the number that was passed in since you never modify it.

The fix is a very simple modification. Where you have

getNextPrime(++num);

... and ...

getNextPrime(num+2);

replace them with

return getNextPrime(++num);

... and ...

return getNextPrime(num+2);

The problem with the algorithm you chose is that it is inefficient. You need to test divisibility using smaller primes only, not all odd numbers, and only up to the square root of the original number.

Implementation is left as an exercise.

Lets try to look at the call stack when we call your function with argument 8;

The first call is : getNextPrime(8). As the number is even, the function goes into the if part and calls itself again with getNextPrime(9). This time the else part kicks in, checks for divisibility in for loop, finds that 9 is divisible so calls the getNextPrime(11). Now getNextPrime(11) goes again the else and the for loop and finds that 11 was prime and returns the number 11 to the caller, but if you look closely, you don't store this value in a variable, the num variable in the getNextPrime call was 9, and when getNextPrime(9) returns it returns that value to getNextPrime(8). In your getNextPrime(8) too you haven't really stored the num variable returned from the recursion call stack. You are just return the num variable defined in that function, which you happened to increment before calling the getNextPrime(11) so this value is 9, and 9 is returned.

Corrected program with the same if else block is given below for your reference.

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

Your return statement works fine but ..you have left 1,2 and 3 out of your logic. 2 is a even prime number and 1 is not a prime number.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM