I have the following code in C++
int factorial_recursivo(int factorial) {
if(factorial <= 1) return 1;
// To show all the factors in each iteration std::cout << factorial << std::endl;
return factorial * factorial_recursivo(--factorial);
}
However, if i write a number n, the result is the factorial of the number n-1.
If i change the last line of code the factorial_recursivo(--factorial) by factorial_recursivo(factorial - 1) works properly.
Why this happen? I even printed the factors in console and it correctly showed. Per example, with factoria_recursivo(5) i got 5 4 3 2, however the result was 24.
You should do value - 1 instead:
return factorial * factorial_recursivo(factorial-1);
Executing:
return factorial * factorial_recursivo(--factorial);
results in unsequenced modification and access to factorial. On my laptop it actually produces 6 regardless of what I input as a parameter. Thank you M.M for asking me to clarify this in the comments. This is an example of undefined behavior.
Unsequencing occurs when the end result depends on which operand gets executed first. A simple example of this would be: arr[j] = arr2[++j]; The result of this would depend on whichever gets executed first, whether it would be arr[j] or arr2[++j].
.
The program has undefined behaviour because the operands of * are unsequenced, and so there are unsequenced read and writes of factorial.
The problem is essentially the same as the cases in this thread: Undefined behavior and sequence points
Related
I'm having a hard time understanding why using a increment operator in a for loop in C++ has a different result than doing 'variable' + 1. The variable in the second case simply isn't remembered after each iteration of the loop:
Take the following code:
#include <iostream>
int main(){
int a{0};
for (int i = 0; i < 5; i++){
std::cout << ++a;
}
return 0;
}
It outputs as expected:
12345
However, if I instead replace ++a with a + 1:
#include <iostream>
int main(){
int a{0};
for (int i = 0; i < 5; i++){
std::cout << a + 1;
}
return 0;
}
I get:
11111
Even if I make the 'a' variable static:
static int a{0};
It still outputs 11111.
Why doesn't 'a + 1' preserve its value after every loop? What would I need to do if I wanted to preserve its value after every iteration without using ++ (for instance, with another operation like a * 2)?
Why doesn't 'a + 1' preserve its value after every loop?
a + 1 is an expression that doesn't assign anything to a. That is a is not affected in any way. This means when you do just a + 1, the value of a is still 0(the old value).
On the other hand ++a has the same effect as:
v---------->assignment done here implicitly
a = a+1
In the above expression ++a, the value of is incremented by 1 so that the new value of a is now 1.
++a is equivalent to the assignment a= a + 1 (or a+= 1). The expression a + 1 alone does not modify a.
C++ will allow you to write std::cout << (a= a + 1);.
a++ is not the same thing as a+1 but as a=a+1.
What's the difference?
Well:
a+1 contains the value, which is one higher than the value of a.
a=a+1 means that, in top of this, this value gets assigned to the variable a, which means something like "replace a by its value plus one".
This gives following possibilities (I also show the difference between a++ and ++a):
int a=3;
cout<<a+1; // output : 4. Value of 'a' equals 3.
cout<<a+1; // output : 4. Value of 'a' equals 3.
cout<<a+1; // output : 4. Value of 'a' equals 3.
int a=3;
cout<<a++; // output : 3. Value of 'a' becomes 4 after having shown it on screen.
cout<<a++; // output : 4. Value of 'a' becomes 5 after having shown it on screen.
cout<<a++; // output : 5. Value of 'a' becomes 6 after having shown it on screen.
int a=3;
cout<<++a; // output : 4. Value of 'a' becomes 4 before showning it on screen.
cout<<++a; // output : 5. Value of 'a' becomes 5 before showning it on screen.
cout<<++a; // output : 6. Value of 'a' becomes 6 before showning it on screen.
Conceptually, the built-in arithmetic operators like + and * evaluate their operands, perform the respective operation with the thusly obtained values, and create a temporary object that contains the result.
The operands, one of which is your a, are only read from, not written to. That is more obvious when you consider that + is commutative, that is, its operands can be swapped without affecting the result: a+1 is by definition the same as 1+a, and clearly you cannot write anything back to the immediate value 1.
Generally, as you certainly know, = is used in C and C++ to write a value to a variable. C, and by means of ancestry also C++, provide shortcuts to write back the result of certain operations to one of their operands: it's the combination of the operator and the assignment =, for example a += 1. Like all assignments, this one is an expression (that is, it has a value) which has the value of the variable after the operation and assignment. Like all other expressions, you can use it as a subexpression, even though that's not very common: cout << (a += 1); would achieve the desired effect (the parentheses are necessary because assignment has about the lowest operator precedence). Because incrementing (and decrementing) by one is so very common, C and C++ have a shortcut for the shortcut: ++a is the same as a+=1, so that one would typically write cout << ++a; (as a side effect obviating the need for parentheses).
I have been programming for a long time and stumbled across something very weird.
Somewhere in my code I had the following code:
for(int i = 0; i < 512; i++){
if((i * 12391823) % 5 == 1){
std::cout << i << std::endl;
}
}
I have already tracked the problem down to this piece of code.
I am using CLion. When compiling a Debug build, the loop is not endless and finishes eventually after printing a few numbers.
Yet when building as Release, it seems to never exit the loop.
...
>>> 15968768
>>> 15968773
>>> 15968778
...
If (i * 12391823) is replaced with a different (smaller) number, this does not happen.
E.g. with (i * 123), it does exit nicely:
...
>>> 482
>>> 487
>>> 492
...
I have also looked at the compile output which displayed the following:
warning: iteration 174 invokes undefined behavior [-Waggressive-loop-optimizations]
16 | if((i * 12391823) % 5 == 1){
| ~~~^~~~~~~~~~~
I do wonder why this would lead to the loop not ending.
It seems to overflow, yet it is not supposed to change i and therefor end the loop at some point, right?
I am very happy for an explanation on this topic!
Greetings
FInn
I do wonder why this would lead to the loop not ending. It seems to overflow, yet it is not supposed to change i and therefor end the loop at some point, right?
The answer is "Undefined Behaviour is undefined". It can do anything. But, the fact that you get a warning from aggressive-loop-optimizations may hint at the reason why loop becomes endless. It is possible that compiler decides to modify your loop into
for(int i = 0; i < 512 * 12391823; i + 12391823){
if(i % 5 == 1){
std::cout << i << std::endl;
}
}
Or maybe even
for(int i = 24783646; i < 512 * 12391823; i + 12391823 * 5){
std::cout << i << std::endl;
}
Both options could act strangely when integer overflow happens.
The solution is to not get into Undefined Behaviour lands. You can do that for example by changing type of i from int to unsigned long long
for(unsigned long long i = 0; i < 512; i++)
You are hitting undefined behavior in the line:
if((i * 12391823) % 5 == 1){
This is because for i larger then 173 the multiplication result exceeds integer range.
When it comes to undefined behavior - you are at the liberty of the compiler. In optimized builds they tend to compile away some (even large) chunks of code in and around the expression which causes it. And as you just experienced - it may even spread to the code which by itself is correct (the exit condition in the for loop).
BTW integer overflow (as far as I know) causes undefined behavior only for signed integers, it is well defined for unsigned types (the result is truncated). You may want o try i of unsigned type (but this still MAY yield results which you didn't expect).
As explained in the comments, the values generated in the loop, specifically this sub-expression:
(i * 12391823)
overflows for larger values of i. This results in undefined behaviour.
The issue is resolved by using a wider type for i, like long long.
Note: If you use an unsigned type, they will wrap around rather than overflow, if their max limit is exceeded.
how does line return((count-2)+(count-1)) works in below cpp program?
ans of the given code is -18 .how to know the ans without running the code
and out of two function count(n-2) and count(n-1) which one is called first and how is it decided?
#include <iostream>
using namespace std;
int count(int n);
int main() {
int n, m;
n = 4;
m = count(n);
cout << m;
}
int count(int n)
{
if (n<0)
{
return n;
}
else
{
return (count(n - 2) + count(n - 1));
}
}
There's no sequencing between the left-hand and right-hand side of the + operator. So which one is evaluated first is unknown (and left up to the compiler).
The only way to figure it out is to step thought he code line by line, statement by statement, expression by expression in a debugger.
However, since each recursive call is not depending on any side-effects they can be executed independently of each other, and therefore the order doesn't matter as the result will always be the same.
We can simply draw a binary tree to know the answer without compiling it. Just start breaking branch into two for count(n-1) and count(n-2) then add all leaves of trees.
Like if we took n as 4 it would be split as 3 and 2, Which would be two branch of 4. Similarly and recursively break nodes in to branch. 3 would be split into 1 and 2 so on. till leaves node is less then 0. In the end add value of all leaves to get the answers.
INTENTION -> A program that adds even numbers only within a range
Strange behavior -> the logical statement is incorrect for adding even numbers, instead the logical statement is correct for adding odd numbers, but the sum of even numbers is the result. As we all know, num & 1 returns true if num is odd, and false if num is even.
Question -> Check my logical statement in the code. Why is the increment of n inline with the logical operator inverting the return value and summing even numbers (which is intended, but unexpected for this logical statement)?
//program to print sum of even numbers
#include <iostream>
int main(){
int n = {0}, result = {0};
while(n < 99) result += n++ & 1 ? n : 0;
std::cout << result << '\n';
}
I was experiencing some random behavior when attempting a simple coding implementation of a bitwise odd number detection. num & 1
This is returning the desired and appropriate value of even nums between 0 and 100, when I'm not using any negation. such as ~num & 1 . Can someone explain to me why the negation isn't necessary, and why its returning even values? Is there some extra behavior to the n++ happening?
NOTE: I understand the syntax is obtuse, that was sort of my intention, to be as obtuse as possible for the sake of experimenting with the language a bit. I'm not asking for a style critique.
Examples
https://repl.it/KG8Z/1 < this should print odd, but what is the unintended side-effect of the ++ operator that is making it print even numbers?
https://repl.it/KG8Z/0 < c++
https://repl.it/KGId/3 < python
I was expecting to need to use the bitwise not operator in c++ to get the desired result, but the results are the same despite the absence of a logical not. How to explain this odd behavior?
When
n++ & 1
executes, lets expect n is odd number at the moment, condition is true.
Post incrementation is applied and n is even when
result += n
executes. Thats why its counting even numbers instead of odd. Modify code to
while(n < 99) result += !(n++ & 1) ? n : 0;
and it will count odd one's.
[expr.cond]/1:
Conditional expressions group right-to-left. The first expression is
contextually converted to bool. It is evaluated and if it is true, the
result of the conditional expression is the value of the second
expression, otherwise that of the third expression. Only one of the
second and third expressions is evaluated. Every value computation and
side effect associated with the first expression is sequenced before
every value computation and side effect associated with the second or
third expression.
Thus, n is "selected" on odd ns in the condition, but at that point, it's already incremented (even).
n & ~1 is not the same as !(n & 1).
I'm working on a fairly easy tracing exercise however I'm not completely understanding why the solution is what it is...
void f( int n) {
if (n>0) {
f(n-1)
cout << n << " ";
}
}
int main () {
f(5);
return 0;
}
the answer is 1 2 3 4 5, however I'm wondering how this is so, since everytime the function f is called it never gets to the cout line...I understand that there is a stacking system where the last function implemented is looked at, however until the factorial example where it returned a value to multiply to the previous n, I'm not understanding how this is similar. Please don't use the factorial example again, I do understand it, but I'm not udnerstanding how the cout is implemented here.. thank you for your help.
Consider the simple case of calling f(1). We pass the if test and make a recursive call to f(0). This call will return doing nothing and continue executing the body of f(1). The next statement is the call to std::cout << 1 << " ";:
// Substitute the parameter with the passed in argument n = 1
void f(1) {
if (1 > 0) {
f(0);
std::cout << 1 << " ";
}
}
You should now be able to handle the case of f(2), and in general f(n). Whenever you are stuck thinking about recursive programs, consider the base cases and then generalize. Write the code out by substituting the function parameters with actual arguments.
It does get to the output line, after the recursive call to f returns.
The important part here is the stopping condition:
if (n>0)
This makes the recursive call only happen if n is larger than zero. And as the recursive call is with the argument n - 1 it will be lower and lower until it's zero and no more calls will be made.
Lets trace it for you, since you are to lazy to do it yourself in a debugger (or on paper):
The first call from main is made. n == 5 and clearly larger than zero, so a recursive call is made with 5 - 1
In the second call, n == 4, still larger than zero so a call is made again with 4 - 1
In the third call, n == 3, still larger than zero so a call is made again with 3 - 1
In the fourth call, n == 2, still larger than zero so a call is made again with 2 - 1
In the fifth call, n == 1, still larger than zero so a call is made again with 1 - 1
In the sixth call, n == 0, which is not larger than zero, so no more calls are made and the function returns.
Returns to n == 1, and so 1 is printed and then the function returns
Returns to n == 2, and so 2 is printed and then the function returns
Returns to n == 3, and so 3 is printed and then the function returns
Returns to n == 4, and so 4 is printed and then the function returns
Returns to n == 5, and so 5 is printed and then the function returns to the main function
That is, this is how it should have worked if it compiled. Now it won't even get this far since you will have compiler errors (with the code as shown in your question).