I had to understand some code which mixes pre- and post-increments in functions. There was one thing that confused me.
So I tried to test some smaller function. But I could not explain following behaviour:
int i = 1;
i = i++ * ++i * 2;
System.out.println("i = " + i);
int x = 1;
x = ++x * x++ * 2;
System.out.println("x = " + x);
The expected output was:
i = 8
x = 8
But actually is:
i = 6
x = 8
Can someone tell me why?
i++ * ++i * 2 --> 1 * 3 * 2 --> 6
++x * x++ * 2 --> 2 * 2 * 2 --> 8
Important values in bold.
The difference between the prefix and postfix increment when returning values in Java can be better summarized by Oracle themselves (my bold again for highlighting purposes):
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. If you are just performing a simple increment/decrement, it doesn't really matter which version you choose. But if you use this operator in part of a larger expression, the one that you choose may make a significant difference.
Source here.
In your specific case, as the postfix evaluates to the original value and the order of operations is left to right for same arithmetic operator - here, only multiplier applies - your operations are translated as above.
Post-increment increases the value of i but does not immediately assign the new value of i.
Pre-increment increases the value of i and is immediately assigned the new value.
Thus, in your example for y, after i++,
i has become 2 but it is still holding on to the previous value of 1.
When ++i occurs, i with the value of 2 will be increased by 1 and simultaneously, assigned the new value of 3. Therefore, 1 * 3 * 2 gives us the value 6 for y.
The same goes for x,
when ++x occurs, x is immediately assigned the new value of 2.
However, when x++ occurs, x is increased by 1 but is still assigned the previous value of 2. Therefore, 2 * 2 * 2 gives us 8.
Related
Consider this code:
public class Incrdecr {
static int x = 3;
static int y = ++x * 5 / x-- + --x;
public static void main(String[] args){
System.out.println("x is " + x);
System.out.println("y is " + y);
}
It evaluates to the following:
x is 2
y is 7
This makes perfect sense, but let's take a quick look at the operator precedence table:
According to this, postfix operators are supposed to be evaluated first. Now, if we go back to our code, we will see that x-- should have been evaluated first, yet it wasn't. What am I not accounting for?
In other words, if we strictly follow the operator precedence table, then the expression would evaluate to:
y = ++x * 5 / 3 + --x;
which, of course, gives us an entirely different result for y.
You are correct in that your expression is evaluated left to right. This is the general evaluation order in Java (there are probably exceptions).
I think you have figured out what really happens:
x is incremented from 3 to 4 and its new value, 4, taken
5 is evaluated as 5
4 * 5 = 20
The value of x, 4, is taken for the division; the division yields 5 and x is decremented to 3.
x is further decremented to 2 before its value is taken for the final addition, which then yields 7.
Except: the compiler is allowed to swap steps only if it can guarantee that the result is the same. Therefore we know the result can only be 7.
Try to keep two concepts apart: evaluation order and operator precedence. They are not the same.
The precedence table tells you that the expression is understood as ((++x) * 5 / (x--)) + (--x) (that’s mostly good because ++(x * 5 / x)-- + --x would not make sense anyway).
To take a different example: f(x) - g(x) * h(x). The mehtods are called left to right: f(), then g() and h() last. The precedence table only tells you that the multiplication is done before the subtraction.
EDIT: Lew Bloch in a comment questioned that x would be evaluated to 4 at any point during calculation. To test this, I made the following variant of your program from the question:
public class Incrdecr {
static int x = 3;
static int y = p(++x) * 5 / p(x--) + p(--x);
private static int p(int i) {
System.out.println("p(): " + i);
return i;
}
public static void main(String[] args) {
System.out.println("x is " + x);
System.out.println("y is " + y);
}
}
This prints:
p(): 4
p(): 4
p(): 2
x is 2
y is 7
So yes, at two points x is evaluated to 4.
http://www.cs.bilkent.edu.tr/~guvenir/courses/CS101/op_precedence.html
Post increment/decrements follow left to right associativity of operators.
Pre increment/decrements follow right to left associativity of operators.
That is to say:
static int y = ++x * 5 / x-- + --x;
(x--) is stored as the current value of x (3) and then the rest is evaluated.
++x is evaluated to x=(x+1) forcing the evaluation of the post-increment because it is an assignment so it becomes (3) then --x is evaluated to x=(x-1) or 2.
This is functionally equivalent:
y = (x=x+1) * 5 / x-- + (x=x-1) (and it will run like this in your Java code)
The resulting equation is:
3 * 5 / 3 + 2.
This question already has answers here:
How do the post increment (i++) and pre increment (++i) operators work in Java?
(14 answers)
Closed 7 years ago.
I missed this question three times on a test. I just can't seem to grasp how to solve this. Any help is much appreciated.
public class Test {
public static void main(String[] args) {
int j = 0;
int i = ++j + j * 5;
System.out.println("What is i? " + i);
}
}
For:
int i = ++j + j * 5;
The variable j is per-incremented by 1 with the expression ++j, that is equal to j+1, changing the value of j to 1. Then following the rules for the order of operations in java, the multiplication is executed (j * 5) or (1 * 5) at this stage, so currently i = 5. Finally to the product of the multiplication j is added (j + 5) or (1 + 5) = 6.
You can check this page where this is explain in a simple way:
http://introcs.cs.princeton.edu/java/11precedence/
As per Java's operator precedence and evaluation order, i is equal to 6. i is set equal to j which is pre-incremented to 1, and added to the product of itself and 5, which is 6.
The thing to note here is the difference between j++ and ++j. See this: The difference between ++Var and Var++
Keeping this in mind, ++j will return 1, and change j's value to 1. So the next part, j*5 is equal to 1*5, which is 5. So overall ++j + j*5 gives you 6.
if ++j appears in the statement, the value of j is first incremented and then the statement is executed. But if j++ appears in the statement, first statement is executed and then the value is incremented.
To simply solve execution part, you can ignore ++ sign and simplify it. But don't forget the order of increment and simplification.
Java has an operator precedence rule which means for any mathematical expression in Java which contains operators, postfixes(j++) and prefixes(++j) are evaluated first. There is also left and right associativity which is how your statement is parsed. Mathematical operators such as +,-,/,* have left to right associativity. Postfixes and Prefixes have right to left associativity.
Looking at the Java Grammar File one finds that
The value of the prefix increment expression is the value of the
variable after the new value is stored
So, ++j is 1 for the current statement.
The value of the postfix increment expression is the value of the
variable before the new value is stored.
So, j++ is 0 for the current statement.
So, (++j) + j * 5 after prefix evaluation becomes (1 + (1 * 5)) = 6.
[Edit]
Thus, statement such as j++ + j * 5 will give you 5 as an answer because j becomes 1 after j++(postfix increment) but j++ itself remains 0.
According to java operator precedence, ++ operator has higher precedence than + and * operators. Here's what happens, step by step:
First ++j happens. Since j is 0, ++j increments j to 1.
Now the expression ++j + 5 * j has become 1 + 5 * 1.
Now we have two operators, + and *. Which one is applied first? See the operator precedence chart and you will find out that * has higher precedence than + . So first 5 * 1 takes place first. After multiplication the expression looks like 1 + 5.
Adding 1 to 5, we get 6. So....i = 6 is the result.
If u want to know more about ++ operator, there are some decent videos on youtube.
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.)
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is there a difference between x++ and ++x in java?
Can anyone please explain me what is happening backyard to these statements?
int x=5;
System.out.println((x++)*x); //Gives output as 30
int x=5;
System.out.println((++x)*x); //Gives output as 36.
int x=5;
System.out.println((x++)*x); //Gives output as 30
You first take x (x = 5) as an operand. Then it's incremented to 6 which is second operand.
int x=5;
System.out.println((++x)*x); //Gives output as 36.
You first increment x by one (x = 6) and then multiply by x => 6 * 6 = 36
Multiplication is left-to-right associative, so the left operand will be evaluated first, then the right operand.
Post-increment operator will evaluate to current value of the variable, and increment it right after.
Pre-increment operator will increment the variable, then evaluate to the incremented value.
(x++) * x (x = 5)
--> 5 * x (increment deferred, x = 5)
--> 5 * x (increment x, x = 6)
--> 5 * 6
--> 30
(++x) * x (x = 5)
--> 6 * x (x is incremented before evaluated into expression, x = 6)
--> 6 * 6
--> 36
I mentioned the associativity here because it will affect the final result. If the associativity of multiplication is right-to-left instead of left-to-right, then the result will be 25 and 30 for post-increment and pre-increment expression respectively.
Assuming you understand that:
++x returns x+1 and increments x, while
x++ returns x and increments x,
the reason for the result is defined by the Java Language Specification #15.17
The multiplicative operators have the same precedence and are syntactically left-associative (they group left-to-right).
So in the first case, x++ is first evaluated, which returns 5 (it is the postfix operator) and adds 1 to x afterwards. Then the result of x++ (5) is multiplied by x (which is now 6) ==> 30
In the second case, ++x is first evaluated, which adds 1 to x and returns 6 (it is the prefix operator). Then the result of ++x (6) is multiplied by x (which is now 6) ==> 36
p++ means use then increment with a copy (copy is extremely local)
++p means increment and use without a copy
p++: use 5 and use incremented thing later in that line
++p: increment and use immediately
Post increment operators do the incrementation after the expression has been calculated.
In your first example, what is actually happening is:-
(x++) * x ; // (now incremented, 6 )
// x (5) * x+1 (6)
In your second example, the increment happens first
(++x) * x; // incremented straight away.
// x+1 (6) * x (now 6)
This might seem simple but it's just stumbled me and my friends...
lets take the following piece of code-
in java
//........
int a=10;
a= a-- + a--;
System.out.print("a="+a);
//........
in c
//........
int a=10;
a= a-- + a--;
printf("a= %d",a);
//.......
where in the former case you get output as 19 in C you get it as 18.
the logic in c is understandable but in java?
in java if its like
int a=10;
a=a++;
in this case the output is 10.
So what's the logic?
a = a-- + a-- causes undefined behaviour in C. C does not define which decrement should be evaluated first.
a-- evaluates to the value of a, and after that it decrements a,
so in Java a = a-- + a-- evaluates like this:
a = (10, decrement a) + (9, decrement a)
The second operand is 9 because first term caused a to be decremented.
In summary: With that expression, C does not define the evaluation order. Java defines it to be from left to right.
I don't know about Java but in C that line of code doesn't have a return value defined in the standard. Compilers are free to interpret it as they please.
In the expression
a = a-- + a--;
you have a lot of sub-expressions that need to be evaluated before the whole of the expression is evaluated.
a = a-- + a--;
^^^ <= sub-expression 2
^^^ <= sub-expression 1
What's the value of sub-expression 1? It's the current value of the object a.
What's the value of the object a?
If the sub-expression 2 was already evaluated, value of object a is 9, otherwise it is 10.
Same thing for sub-expression 2. Its value can be either 9 or 10, depending on whether sub-expression 1 was already evaluated.
The C compiler (don't know about Java) is free to evaluate the sub-expressions in any order
So let's say the compiler chose to leave the --s for last
a = 10 + 10;
a--; /* 19 */
a--; /* 18 */
but on the next compilation the compiler did the --s up front
/* value of sub-expression 1 is 10 */
/* value of sub-expression 2 is 9 */
a = 10 + 9; /* a = 9 + 10; */
or it could even save one of the a-- and use that for the final value of a
/* sub-expression 1 yields 10 and sets the value of `a` to 9 */
/* so yield that 10, but save the value for the end */
a = 10 + ???;
a = 18???; a = 19???;
/* remember the saved value */
a = 9
Or, as you invoked undefined behaviour, it could simply replace your statement with any of the following
a = 42;
/* */
fprintf(stderr, "BANG!");
system("format C:");
for (p=0; p<MEMORY_SIZE; p++) *p = 0;
etc ...
You are post-decrementing. To me, the java result makes more sense.
The first a-- is evaluated as 10, and decrements to 9. 10 is the value of this sub-expression.
The second a-- is evaluated. a is now 9, and decrements to 8. The value of this sub-expression is 9.
So, it becomes 10 + 9 = 19. The two decrements get overwritten by the assignment.
I'd expect 18 if the expression were a= --a + --a.
Have you tried compiling the C version with different optimization flags?
a= a-- + a--;
This invokes undefined behaviour in C/C++. You should not expect consistent results from this statement.
a = 10 + 9
you can try with:
a = a-- + a-- + a--
it returns 27 ( 10 + 9 + 8)...