This question already has answers here:
What is the difference between ++i and i++?
(20 answers)
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Closed 4 years ago.
I've recently started trying to learn C & was doing an exercise that involved creating a recursive factorial function.
Why does the following print out an answer of 24?
#include <stdio.h>
int factorial(int n);
int main(void)
{
int n = 5;
printf("%d\n", factorial(n));
return 0;
}
int factorial(int n)
{
if (n <= 1)
return 1;
else
return n * factorial(--n);
}
If i change the last line to
return n * factorial(n - 1);
I get the expected 120.
I understand that you can't use n-- b/c it only decreases n after the line is processed but whats wrong with --n & why does it give 24?
whats wrong with --n & why does it give 24?
The problem is that --n modifies n, so your line
return n * factorial(--n);
may evaluate like:
return (n - 1) * factorial(n - 1);
because the factorial(--n) is evaluated before the n that is the first term of the expression. On the other hand, the first term could be evaluated before the second, and you'd get the result you expect. Or, something entirely different could happen, because (as M.M and David C. Rankin point out in comments) what happens when you try to use a variable and modify it in the same expression is undefined:
If a side effect on a scalar object is unsequenced relative to either a different side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined.
So let's address your title question:
Does (--n) equal (n - 1)?
The values of --n and of n - 1 are the same, but the former expression has the side effect that it modifies n. You should really think of --n as being shorthand for the expression (n = n - 1).
Related
This question already has answers here:
Is short-circuiting logical operators mandated? And evaluation order?
(7 answers)
Closed 3 years ago.
This function is from my professor's notes:
int ints_is_sorted_r(int* a, int n){
return n <= 1 || (a[0] <= a[1] && ints_is_sorted_r(a+1, n-1));
}
This is my version with many printfs to see what it does
int ints_is_sorted_r(int* a, int n){
printf("n <= 1 = %d\n",(n <=1));
printf("a[0] <= a[1] = %d <= %d\n",a[0],a[1]);
ints_println_special(a,n);
return n <= 1 || (a[0] <= a[1] && ints_is_sorted_r(a+1, n-1));
}
(ints_println_special() is a function from my prof's library that prints the whole array)
My question is, how does the recursion stop? Here's the output from my test:
My guess is that when you have an OR condition and the first one is true it doesn't waste time looking for the right side of the condition because it knows it's going to be true anyway. Am I correct?
My guess is that when you have an OR condition and the first one is
true it doesn't waste time looking for the right side of the condition
because it knows it's going to be true anyway. Am I correct?
Yes, you are correct! It's called "short-circuiting" and there are several good posts here on Stack Overflow that explain and discuss it, like this one.
PS: Note that there could also be (probably will be) such short-circuiting, internally, in the part after the || operator; so, in (a[0] <= a[1] && ints_is_sorted_r(a+1, n-1)), if the first comparison, a[0] <= a[1], is FALSE, then the second won't be evaluated, and the function won't be called recursively in that case.
Below is the recursive function for sum of natural numbers up to n.
int calculateSum(int n) {
if (n == 0){
return 0;
}else{
return n + calculateSum(--n); //Replacing --n with n-1 works
}
}
Input: 5
If I use --n then the output is 10, but when I replace --n with n - 1 then the correct result is returned (15). Why the difference?
As surprising as it might be, the behaviour of the expression
n + calculateSum(--n);
is undefined, because --n not only evaluates to the value of n after being decremented by 1, it also changes n to the new value. The change (a side effect), however, is unsequenced in relation to the other evaluation of n (a value computation) on the left. And according to C11 Appendix J.2., the behaviour is undefined, when
A side effect on a scalar object is unsequenced relative to either a different side effect on the same scalar object or a value computation using the value of the same scalar object (6.5).
More of the same class of errors in this question.
You can consider yourself lucky when you got a wrong value, because your compiler could have also generated code that would return the "correct value"... given the phase of the moon, and the optimization settings, or the number of lines in the calling function...
--n also modifies the local variable n; the expression n-1 just returns the decremented value to pass it on to the recursive call, but does not modify your input-parameter.
In detail for the first iteration with input 5:
Correct is return 5 + calculateSum(5-1);
With --n you would also decrement from n and end up with 4 + calculateSum(4)
#user3386109 & #Yunnosch worded it this way:
With --n you calculate the sum 0...(5-1) instead of 0...5.
See #Antti answer, it explains that it's actually undefined behaviour.
The following code snippet (a Function), you can call it in the main function which will return the sum of n natural numbers recursively
int NNumbers(int n)
{
if(n != 0)
return n + NNumbers(n-1);
else
return n;
}
In your code you are decrementing the value of n and then you are calculating the sum (i,e. Pre-Decrement), since the input is 5, it decrements 1 at each iteration and and then it will go for addition of natural numbers. so you are getting the result 10 instead of 15
Hope this helps for you :)
Thank you
i have written a small function which calculates factorial for a number in C
as follows:
int factNnumbers(int n)
{
if(n == 1)
return 1;
else
return (n*factNnumbers(--n));
}
I call the function shown above as:
factNnumbers(takeInputN());
where the function to take the input (takeInputN) is defined as:
int takeInputN()
{
int n;
printf("\n\nHow many numbers ?? \n ");
scanf("%d", &n);
return n;
}
If I change one line in my factorial code as shown below , my program works perfectly. Otherwise with the above code it prints the factorial of the number input -1 (example if number input is 5, it will print the factorial of 4). Why is this happening?.
int factNnumbers(int n)
{
if(n != 1)
return (n * factNnumbers(--n));
}
The problem is that you're both reading and modifying n in the same expression:
n * factNumbers(--n)
The evaluation of the n argument to * and of the --n subexpression are unsequenced, which gives your code Undefined Behaviour.
The easiest solution (and also, IMO, more expressive), is to say n - 1 where you mean it:
n * factNumbers(n - 1)
Your "improved" code in the bottom of the question is actually even more wrong. There, you have a control path which will return an unspecified value: a clear no-no.
Note: This answer was written while the question still had a C++ tag, and uses C++ terminology. The end effect in C is the same, but the terminology might be different.
You are invoking undefined behaviour, that it works in one version is just an accident:
return (n*factNnumbers(--n));
Do you use n first and then decrement it or the other way around? I don't know and neither does the compiler, it's free to do either of them or format your hard drive. Just use n * f(n - 1).
Also, your "working" version does not return for the n==1 case, which is illegal.
There are two causes of undefined behavior in your code:
Whether n or --n in n * factNnumbers(--n) will be evaluated first is unspecified.See this. You want just n * factNnumbers(n - 1), why decrement? You're not using decremented n afterwards (at least you didn't want to).
You're not returning a value on all control paths, what's going to be returned on n == 1? An indeterminate value that will mess up the whole result.
the rule of decrement:
X = Y-- first passes the value of I to X and decrements after
X = --I first pass and decrements the value decremented X
for your case, you decrement the value of parameter passed as argument to the function factNnumbers. Therefore remedy this error, I invite you to put (n-1) instead of (--n).
I think it’s better to use the tgamma function from math.h for double precision calculations involving factorials (such as Poisson distribution etc.): tgamma(n+1) will give you factorial(n).
Factorial function is increasing very fast, and this will work also for values too big to fit an integer type.
When n<=1 (or == 1 in your code), the factorial function has to return 1. Futhermore the your --n in you code is false and sould be n-1 as:
function factorial(n)
{
if (n<=1)
return 1;
else
return n * factorial(n-1);
}
This question already has answers here:
subexpressions evaluation order
(2 answers)
Closed 5 years ago.
I have tried the following code and got confused:
#include <stdio.h>
int m=3;
int f(void)
{
m--;
return m;
}
int main()
{
m=f()+m; //as + operator is executed from left to right, it is okay that m=2+2
printf("%d\n", m); //m=4, as expected
m=m+f(); //as + operator is executed from left to right, it should be like m=4+3
printf("%d\n", m); //but m=6
m+= f();
printf("%d\n", m);
return 0;
}
plus (+) operator is commutative, but here it seemed that the order of the summands matters!!! (according to the rule of associativity)
Why m is equal to 6 after the execution of m=m+f();?
It looks like the function call will always get preference!!!!
I am not sure whether it's an undefined behavior. m=m+m-- is an undefined behavior, as far as I know, but here the decrement task has been performed in an indirect manner- by a function.
In the question "subexpressions evaluation order", the answer was that "each of func1 and func2 can, if desired, interact with some shared data without having that data change under it in an unexpected way", but here the value of m has been changed by the function f.
I tried this code later and found another interesting thing. The function evaluation precedence is not the matter here- as this shows
#include <stdio.h>
int m;
int f()
{
m--;
return m;
}
int main()
{
m=4;
int x;
x=m+f()+f(); //if f() is evaluated first, then it should be like m=3+2+2
printf("%d\n",x); // but m=8
return 0;
}
m=m+f(); //as + operator is executed from left to right, it should be like m=4+3
printf("%d\n", m); //but m=6
This is correct because function call has highest precedence over + operator.
You can have a look at tbis
I hope this would help you.
This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Closed 5 years ago.
int fact_rec(int n)
{
printf("%d\n",n);
if(n==1) return n;
else return fact_rec(--n)*n;
//else return n*fact_rec(--n); gives same result
//correct output comes for n*fact(n-1)
}
In the above recursive implementation of the factorial function,
fact_rec(5) returns 24. Whereas, if I use
n*fact_rec(n-1)
in place of
n*fact_rec(--n)
the output is correct : 120.
Also, it doesn't matter whether I use
n*fact_rec(--n)
or
fact_rec(--n)*n.
Shouldn't it matter if I use
n*fact_rec(--n)
or
fact_rec(--n)*n?
And shouldn't the output have
been 120 in all the cases?
return fact_rec(--n)*n
is dangerous. The order of argument evaluation is undefined in C (except for &&, ||, comma and ternary operators) so value for second occurrence of n could vary.
The rule of thumb: never use variable you are incrementing/decrementing twice in one expression.
Your confusion seems to be about the order - unlike the other answers, I am assuming you already know what --n does...
The compiler knows it needs the value of fact_rec(--n) before it can evaluate fact_rec(--n)*n whichever way round you write it, so the function is evaluated first, and the value of n multipled has always already been decremented.
There is actually no need to modify n at all. return n * fact_rec(n - 1) takes care of it and is the right way to do it.
--n in your function really means:
int fact_rec(int n) {
printf("%d\n",n);
if(n==1) {
return n;
} else {
n = n - 1; /* <---- effect of --n */
return fact_rec(n)*n;
}
}
The problem is here:
else return fact_rec(--n)*n;
you're decrementing n before the multipliation
so if n starts as 5 it runs as
return fact_rec(4)*4;
Edit: Down voted for a correct answer to the question? I don't get it.