This question already has answers here:
What are the rules for evaluation order in Java?
(5 answers)
Closed 6 years ago.
x=10;
y = --x + x++;
System.out.println(y);
// prints 18
As per the link https://docs.oracle.com/javase/tutorial/java/nutsandbolts/operators.html, postfix increment(x++) has higher precedence than prefix increment/decrement (--x).
Hence x++ (value 10) should be executed before --x (value 11-1=10); so y=20. But How does 'y' become 18?
As it is explained at this link
Associativity and precedence determine in which order Java applies operators to subexpressions but they do not determine in which order the subexpressions are evaluated. In Java, subexpressions are evaluated from left to right (when there is a choice). So, for example in the expression A() + B() * C(D(), E()), the subexpressions are evaluated in the order A(), B(), D(), E(), and C(). Although, C() appears to the left of both D() and E(), we need the results of both D() and E() to evaluate C(). It is considered poor style to write code that relies upon this behavior (and different programming languages may use different rules).
This explains why
--x
is executed and evaluated before than
x++
as it is a sum of two sub-expressions and the whole expression is evaluated from left to right. So the first one is executed before than the x++ one (yes, the post-fix ++ has more precedence in general, but here the sub-expression that includes it is evaluated after the first one).
So, 18 is correct, as you are summing two times 9 to x, as clarified below
x=10;
y = --x + x++;
// y = (10-1) /* now x==9 */ + (9); /* after this x == 10 */
// y = (9) + (9); /* and now x == 10 */
// y == 18 and x == 10
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.
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.
When an expression has two operators with the same precedence, the expression is evaluated according to its associativity. I want to know how the following works:
i=b + b + ++b
i here is 4
So ++b didn't change the first 2 b values, but it executed first, because the execution is from left to right.
Here, however:
int b=1;
i= b+ ++b + ++b ;
i is 6
According to associativity, we should execute the 3rd b so it should be:
1+ (++1) + ( ++1 should be done first). so it becomes:
1 + ++1 + 2 =5
However, this is not right, so how does this work?
You are confusing precedence with order of execution.
Example:
a[b] += b += c * d + e * f * g
Precedence rules state that * comes before + comes before +=. Associativity rules (which are part of precedence rules) state that * is left-associative and += is right-associative.
Precedence/associativity rules basically define the application of implicit parenthesis, converting the above expression into:
a[b] += ( b += ( (c * d) + ((e * f) * g) ) )
However, this expression is still evaluated left-to-right.
This means that the index value of b in the expression a[b] will use the value of b from before the b += ... is executed.
For a more complicated example, mixing ++ and += operators, see the question Incrementor logic, and the detailed answer of how it works.
It's correct, first b is 1, and the second b will be incremented by 1 before addition, so it's 2, and the third b is already 2, and incremented by 1 makes it 3. so It's 6 in total. The expression is evaluated from left to right as you said, thus the third b is already 2 before increment.
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.)
What is the correct sequence of the math operations in this expression in Java:
a + b * c / ( d - e )
1. 4 1 3 2
2. 4 2 3 1
I understand that result is the same in both answers. But I would like to fully understand the java compiler logic. What is executed first in this example - multiplication or the expression in parentheses? A link to the documentation that covers that would be helpful.
UPDATE: Thank you guys for the answers. Most of you write that the expression in parentheses is evaluated first. After looking at the references provided by Grodriguez I created little tests:
int i = 2;
System.out.println(i * (i=3)); // prints '6'
int j = 2;
System.out.println((j=3) * j); // prints '9'
Could anybody explain why these tests produce different results? If the expression in parentheses is evaluated the first I would expect the same result - 9.
Almost everybody so far has confused order of evaluation with operator precedence. In Java the precedence rules make the expression equivalent to the following:
a + (b * c) / ( d - e )
because * and / have equal precedence and are left associative.
The order of evaluation is strictly defined as left hand operand first, then right, then operation (except for || and &&). So the order of evaluation is:
a
b
c
*
d
e
-
/
+
order of evaluation goes down the page. Indentation reflects the structure of the syntax tree
Edit
In response to Grodriguez's comments. The following program:
public class Precedence
{
private static int a()
{
System.out.println("a");
return 1;
}
private static int b()
{
System.out.println("b");
return 2;
}
private static int c()
{
System.out.println("c");
return 3;
}
private static int d()
{
System.out.println("d");
return 4;
}
private static int e()
{
System.out.println("e");
return 5;
}
public static void main(String[] args)
{
int x = a() + b() * c() / (d() - e());
System.out.println(x);
}
}
Produces the output
a
b
c
d
e
-5
which clearly shows the multiplication is performed before the subtraction.
As JeremyP has nicely shown us, the first answer is correct.
In general, the following rules apply:
Every operand of an operator is evaluated before the operation itself is performed (except for ||, &&, and ? :)
Operands are evaluated left to right. The left-hand operand of a binary operator appears to be fully evaluated before any part of the right-hand operand is evaluated.
The order of evaluation respects parentheses and operator precedence:
Parentheses are evaluated first.
Operators are evaluated in order of precedence.
Operators with equal precedence are evaluated left-to-right, except for assignment operators which are evaluated right-to-left.
Note that the first two rules explain the result in your second question:
int i = 2;
System.out.println(i * (i=3)); // prints '6'
int j = 2;
System.out.println((j=3) * j); // prints '9'
Reference documentation:
http://java.sun.com/docs/books/jls/second_edition/html/expressions.doc.html#4779
Tutorial:
http://download.oracle.com/javase/tutorial/java/nutsandbolts/operators.html
It evaluates the expressions in the following order. Variable names are expressions that need to be evaluated.
a + b * c / (d - e)
2 3 5 6
4 7
1 8
9
So, the answer to your question is #1. The order of operations determines the shape of the expression tree (what is the left side of the tree, and what is the right), but the left side is always evaluated first (and the root is evaluated last).
I would imagine that it might evaluate something like this evaluating from left to right.
a+b*c/(d-e)
Action Left Value Right Value
Start Add a b*c/(d-e)
Start Multiply b c
Calc Multiply (since it can)
Start Divide b*c (d-e)
Start Subtract d e
Calc Subtract
Calc Divide
Calc Add
This can be thought of as creating a binary tree representing the calculations and then working from the leaf nodes, left to right, calculating things. Unfortunately my ascii art isn't great but here's an attempt at representing the tree in question:
Add
/\
/ \
a \
Divide
/ \
/ \
/ \
/ \
Multiply Subtract
/\ /\
/ \ / \
b c d e
And I did some tests in C# (I know its not the same but that's where my interests lie and the tests can be easily adapted) as follows:
f = 1;
Console.WriteLine((f=2) + (f) * (f) / ((f) - (f)-1));
Console.WriteLine(2 + 2 * 2 / (2 - 2 - 1));
f = 1;
Console.WriteLine((f) + (f=2) * (f) / ((f) - (f)-1));
Console.WriteLine(1 + 2 * 2 / (2 - 2 - 1));
f = 1;
Console.WriteLine((f) + (f) * (f = 2) / ((f) - (f)-1));
Console.WriteLine(1 + 1 * 2 / (2 - 2 - 1));
f = 1;
Console.WriteLine((f) + (f) * (f) / ((f=2) - (f)-1));
Console.WriteLine(1 + 1 * 1 / (2 - 2 - 1));
f = 1;
Console.WriteLine((f) + (f) * (f) / ((f) - (f=2)-1));
Console.WriteLine(1d + 1d * 1d / (1d - 2d - 1d));
The pairs of console.writeline statements are the algebraic one (using the set a number trick) and a numerical representation showing what the calculation actually does. The pairs produce the same result as each other.
As can be seen the arguments are evaluated in order with any after the assignment being 2 and those before being one. So the order of evaluation of things is simple left to right I think but the order of calculations is as you would expect it to be.
I assume this can be run almost with copy and paste to test in JAVA...
There may be some unnoticed assumptions in here so if anybody does spot logic flaws in here please do call me on them and I'll work them through.
i am assuming that your expression would be something like
x = a + b * c / ( d - e )
the equality operator has right to left order of evaluation. so the expression on the right of = will be evaluated first.
if your refer this precedence chart: http://www.java-tips.org/java-se-tips/java.lang/what-is-java-operator-precedence.html
1) the brackets will be evaluated (d-e), lets say (d - e) = f so the expression then becomes
x = a + b * c / f.
2) Now * and / have same precedence, but the order of evaluation is left to right to * will be evaluated first so lets say b * c = g, so the expression becomes x = a + g /f
3) Now / has the next precedence so g / f will be evaluated to lets say h so the expression will be come x = a + h,
4) lastly evaluating a + h
In your second question, it seems Java is evaluating the part in parenthesis as an assignment, not an mathematical expression. This means that is will not perform parenthetical assignments in the same order as operations in parenthesis.
The results of the calculation are defined by the Operator Order of Precedence. So parentheses have highest precedence here, multiplication and division next highest, and addition and subtraction lowest. Operators with equal precedence are evaluated left to right. So the expression in the question is equivalent to:
a + (b * c) / ( d - e ))
However there is a slight difference between what is normally meant by "being evaluated first" and the operator precedence for getting the correct answer.
"d-e" is not necessarily actually calculated before "a" is calculated. This pretty much doesn't make any difference unless one of the 'variables' in the expression is actually a function. The Java standard does not specify the order of evaluation of components of an expression.
a + b * c / ( d - e )
1 1
2
3
The whole point of operator precedence is to convert the expression into a syntax tree. Here the * and - are at the same level of the tree. Which one is evaluated first is irrelevant for the result and not warrantied.
Edit: Sorry, I got confused by my C background. As others have pointed out, Java has an "Evaluate Left-Hand Operand First" rule. Applying this rule to / tells you that * is evaluated first (your first answer).