This question already has answers here:
Why does this expression i+=i++ differs from Java and C?
(8 answers)
Closed 6 years ago.
I am not understanding why this post increment equation does not increase. I would have thought that after the += operation the value would increment by 1 and then the second time around i would have a 1 value. But the output is an infinite loop of 0 zero. Is anyone able to explain why 'i' doesn't increase.
int i = 0;
for(; ; ) {
if ( i >= 10) break;
i += i++;
}
System.out.println(i);
Let's examine i += i++;
i++ means read the value for i, then increment i.
i += x means evaluate i, then evaluate x and add the 2 and put the result in i.
So, what happens is:
i gets evaluated, it is 0
i++ gets evaluated. it returns 0, and the value for i is set to 1
i += i++ is now i = 0 + 0.
i = 0
Try with ++i to get the result of the incrementation before reading its value.
While the answer from #njzk2 is correct, it is useful to point out why it is correct.
There are other possibilities - for example, why doesn't Java execute the postincrement operator after the assignment? (Answer: because that's not what the Java Language Designers chose)
The evaluation order for compound assignments (things like +=) is specified in the Java Language Specification section 15.26.2. I'll quote how it is defined for Java 8:
First, the left-hand operand is evaluated to produce a variable. If this evaluation completes abruptly, then the assignment expression
completes abruptly for the same reason; the right-hand operand is not
evaluated and no assignment occurs.
Otherwise, the value of the left-hand operand is saved and then the right-hand operand is evaluated. If this evaluation completes
abruptly, then the assignment expression completes abruptly for the
same reason and no assignment occurs.
Otherwise, the saved value of the left-hand variable and the value of the right-hand operand are used to perform the binary operation
indicated by the compound assignment operator. If this operation
completes abruptly, then the assignment expression completes abruptly
for the same reason and no assignment occurs.
Otherwise, the result of the binary operation is converted to the type of the left-hand variable, subjected to value set conversion
(§5.1.13) to the appropriate standard value set (not an
extended-exponent value set), and the result of the conversion is
stored into the variable.
The most important thing is that the value of the left hand expression is saved first, then the right hand is completely evaluated, and then the result of the compound operation is stored in the variable on the left hand side.
No surprise you are getting into infinity loop..
class Demo{
public static void main(String[] args){
int i = 0;
for( ; ; ) {
if (i >= 10)
break;
i = i+i++;
System.out.println(i);
}
}
}
assume the above code, I have just replaced your line with increment with what compiler will substitute.
Now, initially i=0;
So
i = i+i++
results in i = 0 + 0 // and now i is 1
but at the end you again make i equal to 0!
Hence infinity...
Related
This question already has answers here:
How increment and decrement with if condition
(2 answers)
Closed 5 months ago.
class Example{
public static void main(String args[]){
int x=99;
if(x++==x){
System.out.println("x++==x : "+x); //Why this code line is not run?
}
if(++x==x ){
System.out.println("++x==x : "+x);
}
}
}
Why isn't the first println statement executed?
The operands of an expression are evaluated left to right.
In the expression x++ == x, first x++ is evaluated. It increments x by 1, but returns the original value of x. So x++ returns 99.
Then x is evaluated, which returns 100 (since it was incremented by x++).
Since 99 is not equal to 100, this condition evaluates to false.
If you change the expression to x==x++, you'll get true.
The differece between i++ and ++i is very simple.
i++ - means exactly first get the value and then increment it for the further usage
++i - means exactly first increment the value and use the incremented value
Following the shippet x++ == x means following:
Analyze expression from left to the right
Get x = 99 as the left operand and use it in the expression
Increment x and thus x == 100
Get x = 100 as the right operand (note it is already incremented)
99 != 100
Following the shippet ++x == x means following:
Analyze expression from left to the right
Get x = 99 as the left operand
Increment x and thus x == 100 and use it in the expression
Get x = 100 as the right operand (note it is already incremented)
100 == 100
You can see all these logic. E.g. not experienced developer cannot know these details. Therefore the best practice is to avoid such increments in the expression. Just do it before the expression in the single line. In this case the logic will be straight forward and you get much less problems.
Why isn't this an infinite recursive loop?
public static void main(String[] args) {
System.out.println(isSuch(99) + " " + isSuch(100));
}
public static boolean isSuch(int n)
{
System.out.println("n is currently at "+ n);
return n > 2 && !isSuch(n - 2);
}
It is not an infinite recursive loop, because it will eventually stop. It stops because the && operator is a short-circuiting operator. The JLS, Section 15.23, describes the && operator:
The conditional-and operator && is like & (§15.22.2), but evaluates its right-hand operand only if the value of its left-hand operand is true.
When the recursion reaches a level where n is not greater than 2, then the && operator immediately returns false without evaluating the right hand side, which is the recursive call. That effectively makes the case where n is not greater than 2 the base case. Then previous recursive calls invert it with the ! operator, returning true. Both calls return true, and true is printed twice.
It is worth noting that while this is a pretty deep recursion, the stack size was more than enough to handle this. But it's not necessary to be an infinitely recursing loop for a StackOverflowError to occur. All it needs is to recurse far enough. Calling isSuch(99999) is enough to cause a StackOverflowError on my box.
Also, if you had used the non-short-circuiting operator & instead of &&, then it would be an infinitely recursive loop, and a StackOverflowError would occur regardless of what number was originally passed to isSuch.
Short-Circuit Logical Operators
The OR operator results in true when first operand is true, no
matter what the second operand is. The AND operator results in
false when first operand is false, no matter what the second operand
is. If you use the || and &&, Java will not evaluate the
right-hand operand when the outcome can be determined by the left
operand alone.
In your sample code when value of n becomes equal to 2, condition
**n > 2 && !isSuch(n - 2)** immediately becomes false since first operand is false, so next operand will not be evaluated thus isSuch() method will not be called.
This question already has answers here:
Java logical operator short-circuiting
(10 answers)
Closed 7 years ago.
Will this code not evaluate the divide by zero portion of the if statement since the first part evaluates to false? If so, is this true for all cases in all Java IDEs? Or will certain compilers throw the exception?
int n = 0;
int x = 5;
if (n != 0 && x / n > 100) {
System.out.println(" s1");
} else {
System.out.println("s2");
}
From JLS §15.23:
The conditional-and operator && is like & (§15.22.2), but evaluates its right-hand operand only if the value of its left-hand operand is true.
So no, you will not get an exception.
Obviously this assumes that you have a single-threaded or thread safe environment - if you introduce visibility problems into the mix then it's anyone's guess.
Assuming we include the import for SoP, and that thoses lines are written inside a static main, there will be no exception thrown, and s2 will be printed.
X/0 will never be evaluated in your code because && check left expression first, thus, it will never throw anything.
&& is a short-circuit operator evaluated from left to right, so if the operand on the left side of && operator is evaluated to false, evaluation should not continue. BUT I expected that the ++ should be evaluated before && because it has higher precedence, and (from the link):
Operators with higher precedence are evaluated before operators with relatively lower precedence.
In that case, why doesn't count increment in the third line of this code?
int mask = 2;
int count = 0;
if( !(mask > 1) && ++count > 1) { mask += 100; }
System.out.println(mask + " " + count);
No, the way the expression is evaluated goes from left to right, while taking operator precedence into account. So once in a && b the a gets false, b is not evaluated anymore.
JLS §15.23. Conditional-And Operator && says:
The conditional-and operator && is like & (§15.22.2), but evaluates its right-hand operand only if the value of its left-hand operand is true.
Here is a detailed step by step evaluation of how this works:
This is because, when you parse an expression as a human being, you start with the lowest precedence operators first. In this case && has lower precedence then ++.
++a < 0 && foo
^^
start
In order to compute the result of &&, you should know the left operand:
++a < 0 && ++b
^^^^^^^
so compute this
Now, when you want to know the result of ++a < 0, take a look at the lowest precedence operator first, which is <:
++a < 0
^
evaluate this
In order to do that, you will need both left and right operand. So compute them:
++a
0
This is the moment were ++a gets increased.
So, now we are at the bottom. Let's make our way back to the top:
false && foo
And this is where the fact that && is short circuit comes in. Left operand is false, so the right operand expression foo is not evaluated anymore. Which becomes:
false
without the evaluation of the right operand.
Edit: I missed the point of the question. See revisions for semi-detailed explanation of short-circuit evaluation.
Each operand of the logical-AND and logical-OR operators is a separate expression, and thus, treated independently (given its own order of operators to evaluate, according to correct operator precedence).
So, while ++ has the highest precedence in ++count > 1, that expression is never even evaluated (because of the short-circuiting).
You seem to be dissatisfied with the short circuit evaluation explanation. Why is precedence not important here?
Imagine this code:
if( !(mask > 1) && Increment(count) > 1)
Function application (that is, calling a function by writing the brackets) is the highest precedence, yet the function call will never happen. If short circuit evaluation made allowances for precedence, it wouldn't really work at all.
To expand a little - operators such as ++ , - , etc all map to function calls. However, the compiler needs to understand the order that they bind. This is not the order that they are evaluated in.
So a + b * c doesn't mean workout b * c then the sum. It means only this add( a, multiply(b, c)) The order of evaluation is different in the case of && (though not in my example), to make it easier for programmers to write quick code.
To avoid confusion, recall that
if (a && b) {
// do something
}
is semantically the same as:
if (a) {
if (b) {
// do something
}
}
Obviously, if a evaluates to false, the term b will never be seen. In particular, an increment opertor there will not execute.
By recalling this expansion, the behaviour should be easier to understand. It's best to consider && as a shortcut for above nested-if statement. (In the case of having an else statement, you will also need to add two copies of the else code, so it's not as easy.)
A more "exact" representation would be to use a condition method:
boolean condition() {
if (!a) return false;
if (!b) return false;
return true;
}
Again, b will never be evaluated if a returns false already.
if( !(mask > 1) && ++count > 1) { mask += 100; }
What this line indicates is:
!(2>1) ie !(true) ie false
In && left side is false it doesnot futher go for checking rightside
so count is not incremented.
In
int x = 5;
int answer = x++ * 6 + 4 * 10 / 2;
the output is 50, and but why the ++ operator doesn't evaluate the expression to 51?
The ++ is on the x not the result.
why the ++ operator doesn't evaluate the expression to 51?
Can you explain how or why that would work? If you wanted that just do
int answer = x * 6 + 4 * 10 / 2 + 1;
The assignment is using the postfix operator which increments after the statement is executed.
The JLS mentions this:
The value of the postfix increment expression is the value of the
variable before the new value is stored.
For more details see the full specification entry.
Postfix operator is evaluates after execution of statement.
According to java
The increment/decrement operators can be applied before (prefix) or after (postfix) the operand. The code result++; and ++result; will both end in result being incremented by one. The only difference is that the prefix version (++result) evaluates to the incremented value, whereas the postfix version (result++) evaluates to the original value.
The defined effect of the ++ postfix operator is that the variable x gets incremented, as if you wrote x = x+1, but the value of the expression x++is the value before the increment. If you want to have th esame effect regarding how xchanges, but use the after avlue in the surrounding expression, you need to use ++x. And if you actually didn't want to increment the contents of x at all, use (x+1).
(It is however not defined, I think, when the assignment of the incremented value to x takes place - it might even be afer anwser obtains its value; on the other hand, usually x++ is almost atomic.)