I'm currently taking a class for c++ and we are learning about recursion and in class my professor used this function as an example of recursion, the function is meant to return the smallest digit in a number and is:
int smallD(int n) {
if (n < 10) return n;
int x = smallD(n / 10);
if (x < n % 10) return x;
else return n % 10;
}
I'm confused on how setting x to the recursive call works, would the function not keep running n / 10 until n is < 10, I just really don't understand the concept and could use some pointers as to how this function works.
Here's something that helps to understand recursion. Add print statements to observe the code as it recursively calls itself and pass and "indent level" to help as well.
Take the original minified code and expand it to something more readable and add extra debugging information to it.
int smallD(int n, const std::string& indent) {
cout << indent << "enter: smallD(n=" << n << ")" << endl;
if (n < 10) {
cout << indent << "n < 10 => returning: " << n << endl;
return n;
}
cout << indent << "about to recurse inovking smallD(" << n / 10 << ")" << endl;
int x = smallD(n / 10, indent+" "); // grow the indent by 2 spaces
cout << indent << "return from recursion, result is: " << x << endl;
cout << indent << "x=" << x << " n=" << n << " n%10=" << n % 10 << endl;
if (x < n % 10) {
cout << indent << "x is less than n%10, returning: " << x << endl;
return x;
}
cout << indent << "x is greater than or equal n%10, returning: " << n%10 << endl;
return n % 10;
}
Let's try it out by invoking smallD(8942468, "")
enter: smallD(n=8942468)
about to recurse inovking smallD(894246)
enter: smallD(n=894246)
about to recurse inovking smallD(89424)
enter: smallD(n=89424)
about to recurse inovking smallD(8942)
enter: smallD(n=8942)
about to recurse inovking smallD(894)
enter: smallD(n=894)
about to recurse inovking smallD(89)
enter: smallD(n=89)
about to recurse inovking smallD(8)
enter: smallD(n=8)
n < 10 => returning: 8
return from recursion, result is: 8
x=8 n=89 n%10=9
x is less than n%10, returning: 8
return from recursion, result is: 8
x=8 n=894 n%10=4
x is greater than or equal n%10, returning: 4
return from recursion, result is: 4
x=4 n=8942 n%10=2
x is greater than or equal n%10, returning: 2
return from recursion, result is: 2
x=2 n=89424 n%10=4
x is less than n%10, returning: 2
return from recursion, result is: 2
x=2 n=894246 n%10=6
x is less than n%10, returning: 2
return from recursion, result is: 2
x=2 n=8942468 n%10=8
x is less than n%10, returning: 2 // <== this is the final result
So hopefully, that will help you understand how the recursion works.
Recursive functions work exactly like non-recursive functions.
One common mistake is to try to think about all the recursive calls at once, as if they had a shared state, but one key ingredient to understanding a recursive function is actually to ignore the recursion and just "think locally".
Perhaps working through an example would clarify things.
Let's look at smallD(321), replacing n in the body of the function with its value.
smallD(321)
if (321 < 10) return 321;
int x = smallD(321 / 10);
if (x < 321 % 10) return x;
else return 321 % 10;
The first condition is clearly false, and in order to determine x, we need smallD(321/10), which is smallD(32).
smallD(32)
if (32 < 10) return 32;
int x = smallD(32 / 10);
if (x < 32 % 10) return x;
else return 32 % 10;
The first condition is false again, so we keep going with smallD(32/10).
smallD(3)
if (3 < 10) return 3;
int x = smallD(3 / 10);
if (x < 3 % 10) return x;
else return 3 % 10;
Now the first condition is true, so the result here is clearly 3.
Now we can go back and use the value of x in each call that was left waiting.
smallD(32)
...
if (3 < 32 % 10) return 3;
else return 32 % 10;
And 3 < 32 % 10 is false, so we return 32 % 10 - 2 to the caller.
smallD(321)
...
if (2 < 321 % 10) return 2;
else return 321 % 10;
And 2 < 321 % 10 is false, so we return 321 % 10, which is 1.
Your intuition is not completely off: The function does indeed "keep running n/10 until n is <10" - but it's in different calls to the same function.
Your program keeps a stack of functions calls. Each function you call puts a (so-called) "frame" on top of everything that is currently on the stack. Inside that frame "live" all the variables "belonging" to that function call. When the function exits, it deletes its own frame from the stack. The currently executing function's frame is on the top of the stack. So, let's see what happens if you call smallD(123):
You start with something else on the stack, at least your main(). Your call to smallD(123) puts the frame for smallD(123) on the top of the stack. This frame contains the variable n = 123. Lets call this frame stack frame A.
Since n >= 10, your smallD(123) calls smallD(123 / 10), i.e., smallD(12) (integer division basically truncates in C++). So, you put another frame on top of your stack. This stack frame corresponds to smallD(12) and contains the variable n = 12. Let's call this stack frame B.
Again, n >=10, so the call to smallD(12 / 10) (i.e., smallD(1)) happens. A stack frame (call it C) is created for this new call, with n = 1.
Now n < 10 holds! The last function call (in stack frame C) returns the value 1 and deletes its own stack frame (frame C).
Stack frame B (where n = 12) is now on top and execution of smallD(12) continues. Since stack frame C has returned 1, stack frame B now contains x = 1. The comparison (x < n % 10) is true (1 < 2), and stack frame B return x = 1.
The same happens in stack frame A again, and stack frame A (which corresponds to our original smallD(123) call) returns 1.
So you see, indeed "division until n < 10" happened, but in different (recursive!) calls to smallD.
You can break down almost every recursive call into the base case (the simplest) and the recursive case. In this case:
The base case is when the number has only one digit: this means that is lesser than 10 (which is the first number with two digits).
if (n < 10) return n;
There is no other digit to compare it to, so return it directly.
The recursive case is any other case that is not the base. Now our digit has two or more digits, so:
And learn what is the smallest digit of all the digits except the last one with the recursive call x = smallD(n / 10)
Then we compare the result to the last digit, which we didn't include before, and return the smallest.
To understand better the process behind the calls, you could print some information and observe it. Try something like this:
int smallD(int n) {
if (n < 10){
std::cout << "Base case. Return " << n << std::endl;
return n;
}
std::cout << "Recursive case: " << n << std::endl;
std::cout << "Compare " << n % 10 << " with smallest of " << n/10 << std::endl;
int x = smallD(n / 10);
int ret;
if (x < n % 10) ret = x;
else ret = n % 10;
std::cout << "Smallest of " << n << " is " << ret << std::endl;
return ret;
}
Related
This question already has answers here:
C++ "return" without value [closed]
(7 answers)
Closed 6 months ago.
I couldnot find a logical reason as how this return statement is working. As much as i read,it should return undefined but the program takes it straight to the recursive call
function below
#include <iostream>
using namespace std;
// Recursive function to print the pattern without any extra
// variable
void printPattern(int n)
{
// Base case (When n becomes 0 or negative)
if (n ==0 || n<0)
{
cout << n << " ";
return;
}
// First print decreasing order
cout << n << " ";
printPattern(n-5);
// Then print increasing order
cout << n << " ";
}
// Driver Program
int main()
{
int n = 16;
printPattern(n);
return 0;
}
the output of above code is
16 11 6 1 -4 1 6 11 16
Recursion isn't special. Here's your function again, but I hid the name so you can't see which function it is.
void XXXXXXXXXX(int n)
{
// Base case (When n becomes 0 or negative)
if (n ==0 || n<0)
{
cout << n << " ";
return;
}
// First print decreasing order
cout << n << " ";
printPattern(n-5);
// Then print increasing order
cout << n << " ";
}
What does XXXXXXXXXX(-1) do? That's right: it prints -1
What does XXXXXXXXXX(16) do? That's right: it prints 16, then it prints the pattern for 11, then it prints 16 again.
Now can you see why XXXXXXXXXX(16) prints 16 at the start and the end?
return (irregardless if the function is recursive or not) will pass an optional value to caller, and execution will then continue in caller.
I am trying to create a program to print first 200 elements following a specific numerical series condition which is
1-1-3-6-8-8-10-20
But instead of showing, just 200 elements is showing 802. I assume is because of the code inside the for loop. I have hours thinking on how to reduce that code to the job and I cannot think anything else. I am getting frustrated and need your help.
The exercise is on the code comments
//Print the following numerical series 1-1-3-6-8-8-10-20 until 200
#include <stdafx.h>
#include <iostream>
#include <stdlib.h>
using namespace std;
int main()
{
int Num1=200, z = 0, x = 1, y = 1;
cout << "\n\n1,";
cout << " 1,";
for (int i = 1; i <= Num1; i++)
{
z = y + 2;
cout << " " << z << ","; //It will print 3
z = z * 2;
cout << " " << z << ",";//It will print 6
z = z + 2;
cout << " " << z << ",";//It will print 8
z = z;
cout << " " << z << ",";//It will print 8
y = z;
}
cout << "\n\n";
system("pause");
return 0;
}
You're looping 200 times, and each time you loop, you're printing out 4 different numbers. You're also printing twice at the start so thats 2 + 4 * 200 = 802, which is where your 802 number output is coming from.
I assume is because of the code inside the "for" loop but I've hours
thinking on how to reduce that code to the job and I cannot think
anything else. I'm getting frustrated and need your help.
So you basically wanna simplify your code. Which can be done by noticing the repetitions.
There you can find only two types of change in the series; either a +2 or x2 with the previous element.
In each iteration this can be achieved by:
If reminder i%4 == 1 or i%4 == 3, need an increment of 2 (assuming 1 <= i <= MAX)
If reminder i%4 == 0, nothing but a multiplication of 2.
When you do like so, you can simply neglect, printing of first two ones and other complications in the total numbers in the series.
Also not that, you are trying to get 200 terms of this series, which increases in each step very fast and exceed the maximum limit of int. Therefore, long long is needed to be used instead.
The updated code will look like this:
#include <iostream>
typedef long long int int64;
int main()
{
int size = 200;
int64 z = -1;
for (int i = 1; i <= size; i++)
{
if ((i % 4 == 1) || (i % 4 == 3)) z += 2;
else if (i % 4 == 0) z *= 2;
std::cout << z << "\n";
}
return 0;
}
See the Output here: https://www.ideone.com/JiWB8W
So in my class we are studying recursive functions. But I just do not understand how they work.
I'll use this code as an example.
// n is written to the screen vertically
// with each digit on a separate line.
void write_vertical(int n) {
if (n < 10)
{
cout << n << endl;
}
else // n is two or more digits long
{
write_vertical(n/10);
cout << (n % 10) << endl;
}
}
So if int n = 123; it will print each digit on its own line.How does this happen? how does this function work step by step?
Testing by random number (13)
Let's take 13 for an example. Well it's not less than 10, so it will execute the else block, and it will immediately execute the function itself with 13/10, which (as an integer) is 1. Now 1 is less than 10, so it will print 1 onto the screen with a new line because of endl. Now it will return back to the previous function call it had (before calling the function again with argument 1) and execute 13%10. 13 modulus 10 is 3, since its remainder becomes 3, with a new line (again because of endl). And voila, you printed the number in a vertical line!
For future
You should use a pencil and a paper, and debug it yourself manually just like we did above. OR even better use a debugger like GDB! This is an excellent quick startup on how to debug with GDB.
Recursion is simple. Assume you've already written your function; then use it.
Here it's the other way around - you are trying to figure out what the function does. Just the same, when you call it, it always does the same stuff.
So, in a general case of a number n > 10, what is n/10 (integer division)? It's that number without its last decimal digit.
What's n % 10? It's the number's last decimal digit.
So, your definition reads:
doing_something for a number `n` IS
doing_it for this number without its last decimal digit
(if there's something left, that is);
then printing its last decimal digit and a newline after it.
That's all.
1:
if(123 < 10) // fails
cout << 123; // skipped
else
{
recurse(123 / 10); // recurse(12) converted to int
cout << 123 % 10; // i'll be back here wait
}
2:
if(12 < 10) // fails
cout << 12; // skipped
else
{
recurse(12 / 10); // recurse(1)
cout << 12 % 10; // wiat I'll be back
}
3:
if(1 < 10) // succeeds! so now else executed
cout << 1; // printed
nothing is below until return of functions so we return
to 2:
cout << 12% 10; // (12 % 10 = 2) was wating it's its time
continue below: nothing below so return from function 2 to 1:
in 1:
cout << 123 % 10; // it was waiting so now it's its time
cout << 123 % 10; // 123 % 10 = 3
go below: nothing untile the end of function so retrun to main
where function was called first time (to the line after the call )
the result: 123
Im having trouble with the function taylor2 not returning a value if i input anything over 2. If I enter 0-2 it outputs the correct value but anything over 2 and I just get a flashing underscore with no data returned.
void taylor2(double x)
{
double total = 1;
int i = 0;
int count = 1;
double temp = 1;
do
{
{
if (i % 2 == 1)
{
temp = (pow(x, i * 2 + 2) / factorial(i * 2 + 2));
total += temp;
}
else {
temp = (pow(x, i * 2 + 2) / factorial(i * 2 + 2));
total -= temp;
}
}
count++;
i++;
} while (fabs(temp) >= .0001);
cout << "The last recoreded temporary value was: "<<temp << endl;
cout << "The computed value for cosine is : "<< total << endl;
cout << "It took " <<count << " values to calculate the value of the function to .0001 places"<< endl;
cout << endl;
}
I suspect that factorial is returning an int. If int is 32 bit (very common), then factorial will overflow once the argument reaches 13 (i = 5 in your case). Signed integer overflow is undefined behaviour in C++.
You could use a std::uint64_t (an unsigned 64 bit integer). This will allow you to evaluate a few larger factorials.
For more reference, see Calculating large factorials in C++
Better still, use a recurrence relation between your Taylor terms.
I feel a little dumb asking this, but here we go...
When trying to follow the Recursion example at the following website http://www.cplusplus.com/doc/tutorial/functions2/, I ran into a road bump that has me perplexed.
I altered the code slightly just to get my head around the code in the recursion example and I pretty much have my head around it, but I can't figure out why the variable 'n' increments in 'Pass B' when I have not told the program to increment 'n'.
Could you please help explain this?
#include <stdlib.h>
#include <iostream>
using namespace std;
long factorial (long n)
{
if (n > 1)
{
long r(0);
cout << "Pass A" << endl;
cout << "n = " << n << endl;
cout << "r = " << r << endl;
r = n * factorial (n-1);
cout << "Pass B" << endl;
cout << "n = " << n << endl;
cout << "r = " << r << endl;
return (r);
}
else
return (1);
}
int main ()
{
long number;
cout << "Please type a number: ";
cin >> number;
cout << number << "! = " << factorial (number) << endl;
system ("pause");
return 0;
}
That's because you are unrolling the recursion.
You are not really incrementing n you are just returning to previous function call where n was n+1 before you called factorial(n-1) ...
When you start you go up to
r = n * factorial (n-1);
which will cause another function call to the factorial.
You keep doing that (start from beginning of your function and go up to the call to factorial with n decremented by 1) until you eventually end up in a function call to factorial where n<=1.
In which case you return 1, but you return to previous call of factorial where n was 2, you do the multiplication (n * whatever was returned by factorial) and you finish the B path of that call and return r.
But you again return to the previous function call where you do the multiplication part and finish the B path and so on ...
factorial(5)
factorial(4)
factorial(3)
factorial(2)
factorial(1)
return 1
return r
return r
return r
return r
You see all "Pass A"-s in order and then all "Pass B"-s in reverse order which gives the impression that n increments eventhough you only see the originally passed n's.
It seems to me that your program works correctly and should output something like this for number=3 (Line breaks removed for readability):
Pass A n=3 r=0 [1]
Pass A n=2 r=0 [2]
Pass B n=2 r=2 [3]
Pass B n=3 r=6 [4]
So I think I can see how you would conclude that the n is incrementing in pass B but this in fact not the case.
You need to keep in mind that n is a function local variable so in this case the n printed in [3] is a DIFFERENT instance of the local variable to the n in [4].
The values of n printed in [1] and [4] are from the top call of the function (where n=3), the values printed in [2] and [3] are the call in the top version of factor (i.e n-1).
If you notice, Pass B is not really passing through the function the second time, it only print the results of the recursion.
So A print 4, 3, 2, etc, while backwords B prints 4 3 2 1 (ie 2 3 4)
Please type a number: 4
Pass A
n = 4
r = 0
Pass A
n = 3
r = 0
Pass A
n = 2
r = 0
Pass B
n = 2
r = 2
Pass B
n = 3
r = 6
Pass B
n = 4
r = 24
4! = 24
Press any key to continue . . .
Try replacing the second r prints as
cout << "Pass B" << endl;
cout << "n = " << n << endl;
cout << "r = " << r << " --- NOTICE RESULT ACCUMULATING AS WE UNNEST THE RECURSION" <<endl;
PS C:\temp> .\r.exe 4
Please type a number: 4
Pass A
n = 4
r = 0
Pass A
n = 3
r = 0
Pass A
n = 2
r = 0
Pass B
n = 2
r = 2 --- NOTICE RESULT ACCUMULATING
Pass B
n = 3
r = 6 --- NOTICE RESULT ACCUMULATING
Pass B
n = 4
r = 24 --- NOTICE RESULT ACCUMULATING
4! = 24
Press any key to continue . . .
Pass B is printed when it is "unwinding" the recursion. It recursed until it hit the "else return (1);" part and then started backing out. Because it called itself with one less for n each time on the way in, it appears to be incrementing as it backs out.
The value of n in pass A and pass B will always be the same as you are not changing it anywhere in between. You pass n-1 to a recursive call but that does not change the value of n.
The reason why you might be confused is that you don't see pass A and pass B for a given n (n>2) next to each other.
When n=2, you'll see:
pass A for n=2
pass B for n=2
When n=3, you'll see:
pass A for n=3
pass A for n=2 // cuz of recursive call.
pass B for n=2
pass B for n=3 // looks like n has increment here..but this 'pass B' pairs with first pass A
Because that's when the recursion rewinds.
Maybe it would be easier to think about the case when n is 2. In that case you enter the conditional block and recurse after "Pass A". When you recurse n is 1, and so you return through the else block. When you return you are back at the previous frame of the recursion, where n is 2. r gets updated according to the result of the recursion call, 2*1, but n remains 2 as in the previous frame.
factorial(2)
factorial(1)
factorial(2)
If n would be initially any larger value then you'd keep rewinding, and n would restore its value to each value it had prior to each recursion.
factorial(3)
factorial(2)
factorial(1) // returns 1
factorial(2) // r=2*1
factorial(3) // r=3*2
Some of the answers use indentation to make it easier to understand what's happening - you case use the same effect to make your own debug output more comprehensible:
Try and change your function to something like this:
long factorial (long n, std::string prefix= "") // default parameter
...
cout prefix << "Pass A" << endl;
cout prefix << "n = " << n << endl;
cout prefix << "r = " << r << endl;
r = n * factorial (n-1, prefix+ " "); // increase indentation
...etc...
My use of std::string may be a bit flaky, but you'll get the idea. Your output should now look like this.
Please type a number: 4
Pass A
n = 4
r = 0
Pass A
n = 3
r = 0
Pass A
n = 2
r = 0
Pass B
n = 2
r = 2
Pass B
n = 3
r = 6
Pass B
n = 4
r = 24
4! = 24