简体   繁体   中英

How does that recursive function work?

Might be a very basic question but I just got stuck with it. I am trying to run the following recursive function:

   //If a is 0 then return b, if b is 0 then return a,
   //otherwise return myRec(a/2, 2*b) + myRec(2*a, b/2)

but it just gets stuck in infinite loop. Can anybody help me to run that code and explain how exactly that function works? I built various recursive functions with no problems but this one just drilled a hole in my head. Thanks.

Here is what I tried to do:

#include<iostream>

int myRec(int a, int b){

    if (a==0){
        return b;
    }

    if (b==0){
        return a;
    }
    else return myRec(a/2, 2*b) + myRec(2*a, b/2);
}

int main()
{

    if (46 == myRec(100, 100)) {
        std::cout << "It works!";
    }
}

Well, let us mentally trace it a bit:

Starting with a, b (a >= 2 and b >= 2)  
myRec(a/2, 2*b) + something  
something + myRec(2*a', b'/2)

Substituting for a/2 for a' and 2*b for b', we get myRec(2*(a/2), (b*2)/2) , which is exactly where we started.

Therefore we will never get anywhere.

(Note that I have left out some rounding here, but you should easily see that with this kind of rounding you will only round down a to the nearest even number, at which point it will be forever alternating between that number and half that number)

So MyRec(2,2) = MyRec(1,4) + MyRec(4,1)
And MyRec(1,4) = MyRec(.5,8) + MyRec(2,2)
So MyRec(2,2) = MyRec(.5,8) + MyRec(2,2) + MyRec(4,1)
Oops.

(The .5's will actually be zeroes. But it doesn't matter. The point is that the function won't terminate for a large range of possible inputs.)

I think you are missing on some case logic. I last program in C ages ago so correct my syntax if wrong. Assuming numbers less than 1 will be converted to zero automatically...

#include<iostream>

int myRec(int a, int b){
    // Recurse only if both a and b are not zero
    if (a!=0 && b!=0) {
        return myRec(a/2, 2*b) + myRec(2*a, b/2);
    }
    // Otherwise check for any zero for a or b.
    else {
        if (a==0){
            return b;
        }
        if (b==0){
            return a;
        }
    }
}

UPDATE:

I have almost forgot how C works on return ...

int myRec(int a, int b){
    if (a==0){
        return b;
    }
    if (b==0){
        return a;
    }
    return myRec(a/2, 2*b) + myRec(2*a, b/2);
}

VBA equivalent with some changes for displaying variable states

Private Function myRec(a As Integer, b As Integer, s As String) As Integer
    Debug.Print s & vbTab & a & vbTab & b
    If a = 0 Then
        myRec = b
    End If
    If b = 0 Then
        myRec = a
    End If
    If a <> 0 And b <> 0 Then
        myRec = myRec(a / 2, 2 * b, s & "L") + myRec(2 * a, b / 2, s & "R")
    End If
End Function

Sub test()
    Debug.Print myRec(100, 100, "T")
End Sub

Running the test in Excel gives this (a fraction of it as it overstacks Excel):

T: Top | L: Left branch in myRec | R: Right branch in myRec

立即输出

The root cause will be the sum of the return which triggers more recursive calls.

Repeating of the original values of a and b on each branch from level 2 of the recursive tree...

图

Expanding on gha.st's answer, consider the function's return value as a sum of expressions without having to worry about any code.

Firstly, we start with myRec(a,b). Let's just express that as (a,b) to make this easier to read.

As I go down each line, each expression is equivalent, disregarding the cases where a=0 or b=0.

(a,b) = (a/2, 2b) + (2a, b/2) = (a/4, 4b) + (a, b) + (a, b) + (4a, b/4)

Now, we see that at a non-terminating point in the expression, calculating (a,b) requires first calculating (a,b).

Recursion on a problem like this works because the arguments typically tend toward a 'base case' at which the recursion stops. A great example is sorting a list; you can recursively sort halves of the list until a list given as input has <= 2 elements, which is trivial without recursion. This is called mergesort.

However, your myRec function does not have a base case, since for non-zero a or b, the same arguments must be passed into the function at some point. That's like trying to sort a list, in which half of the list has as many elements as the entire list.

Try replacing the recursion call with:

return myRec(a/2, b/3) + myRec(a/3, b/2);

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