public static void main(String[] args) {
int A=5;
int B=2;
A *= B*= A *= B ;
System.out.println(A);
System.out.println(B);
}
When I calculated this problem on paper I found A=200 B=20, but when I write it down to eclipse it shows A=100 B=20
Can you explain the solution like solving on the paper?
I tried to solve in Eclipse and by myself.
How do we solve it?
Starting off with A=5, B=2
A becomes A * B * A * B, which is 100, and
B becomes B * A * B, which is 20.
In more detail:
A *= B *= A *= B
is
A = A * (B = B * (A = A * B))
That resolves to
A = 5 * (B = 2 * (A = 5 * 2))
which means
A = 5 * (B = 2 * (A = 10)) // set A to 10
A = 5 * (B = 2 * 10)
A = 5 * (B = 20) // set B to 20
A = 5 * 20
A = 100 // set A to 100
This has to do with evaluation of operands taking place before order of operators (precedence).
Before operators are executed, the operands are evaluated, which in Java always take place in a left-to-right order.
The leftmost A is evaluated as 5, then the leftmost B is 2, then the second A is 5 and the second B is also 2. These values are saved for later computation.
The JLS, Section 15.26.2, deals with the procedure of evaluating a compound assignment operator.
If the left-hand operand expression is not an array access expression, then:
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.
(bold emphasis mine)
Then the operators are executed, with *= having right-associativity. This means that operation proceeds right-to-left. The rightmost A *= B is executed, assigning 10 to A. The the middle B *= A is executed, assigning 20 to B. However, when the leftmost A *= B is executed, the saved value of A is still there -- 5. When multiplied by 20, 100 is assigned to A.
A *= B*= A *= B; // A is now 100
If we break this up into 3 statements, then you will get the expected 200, because A will be evaluated again as part of the last statement as 10, not 5, because the saved value for A is now 10.
A *= B;
B *= A;
A *= B; // A is now 200
Related
int a = 6;
int b = 5;
System.out.print(a *= a++ - (a++) * b);
result out -174
I thought (a++) -> 6
and following the operation ordering, 7 - (6) * 5 => -23
then a should be now 8.
so 8 *= -23 => -184 is what I thought
Please help me out step by step which was wrong and I misunderstand.
Thanks
According to the Java Language Specification section 15.7.1,
The left-hand operand of a binary operator appears to be fully evaluated before any part of the right-hand operand is evaluated.
So in your case, the unparenthesised a++ is evaluated before (a++) * b, which makes the right hand side of the assignment equal to 6 - 7 * 5. That's equal to -29, and multiplying a by -29 gives -174.
So as the title shows, I've got a function that uses a temporary array, and I want to write a value into it from another array, and then multiply the two value with itself.
Example:
float[] a = {0, 0}
a[0] *= a[0] = b[n ];
a[1] *= a[1] = b[n + 1];
I would expect the above would do the following:
a[0] = b[n ];
a[0] *= a[0]; //(aka: a[0] = a[0] * a[0])
a[1] = b[n + 1];
a[1] *= a[1];
Though that behavior doesn't seem to be whats happening. Instead it seems just multiply whatever the original value held in "a" was with whatever value was held in "b" like so:
a[0] = a[0] * b[n ];
a[1] = a[1] * b[n + 1];
It was always my understanding that whatever comes after the "=" is evaluated first, as seen when you do:
float a, b;
a = b = 5;
//"a" and "b" both equal "5" now.
Being that that is the case, would it not show that my original example should work?
Can anyone explain whats going on and why this code doesn't work as intended?
I think the answers so far are not correct. What comes into play is the evaluation of compound expressions like a *= b. In short, the value of the left hand side is computed before the right hand side. From the JLS (emphasis mine):
At run time, the expression is evaluated in one of two ways.
If the left-hand operand expression is not an array access expression,
then:
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.
In your example:
a[0] *= a[0] = b[n ];
value of a[0] is computed and stored in say tmp
a[0] = b[n] is evaluated, giving the value of b[n] (and changing the value of a[0] to b[n])
tmp * a[0] is computed
the result of the last step is assigned to a[0]
So, what you get is effectively a[0] *= b[n].
EDIT: About the confusion about right-to-left-evaluation of assignments: I did not find that terminology used in the JLS, and IMHO it is not correct (although it is used in the Java tutorials). It is called right-**associative* assThe JLS says this about assignments:
There are 12 assignment operators; all are syntactically
right-associative (they group right-to-left). Thus, a=b=c means
a=(b=c), which assigns the value of c to b and then assigns the value
of b to a.
Referring to the Java documentation:
All binary operators except for the assignment operators are evaluated from left to right; assignment operators are evaluated right to left.
So what is happening in your case of a[0] *= a[0] = b[n ]; is that you assign a[0] the value of b[n] and then you multiply the original a[0] by that new value. So your expression is effectively a[0] *= b[n].
Personally, I don't use an assignment operator twice on a single line, it can be confusing to read.
Assignment operators (unlike most other operators) are evaluated from right to left in Java (documentation). This means that the following:
a[0] *= a[0] = b[n];
is actually evaluated as:
a[0] *= (a[0] = b[n]);
The quantity in parentheses is an assignment, and returns the value b[n], but does not change the value of a[0]. Then, the following final assignment is made:
a[0] = a[0] * b[n]
Both *= and = are assignment operators, and have the same level of precedence. So in this case, the right to left rule applies.
A key point that doesn't seem to have been pointed out in the answers yet is that *= isn't merely an assignment operator, but rather a compound assignment operator.
The language spec says that the following are equivalent:
E1 op= E2
<=>
E1 = (T) ((E1) op (E2))
where op= is something like *=, += etc.
As such:
a[0] *= a[0] = b[n ];
is equivalent to:
a[0] = a[0] * (a[0] = b[n]);
and the a[0] is evaluated before the (a[0] = b[n]), because of the left-to-right evaluation order.
So:
This reads the value from a[0] (call this "A")
It reads the value from b[n] (call this "B")
It assigns B to a[0] (*)
And then multiplies A * B (call this "C")
And then stores C back in a[0].
So yes, this is equivalent to multiplying whatever is in a[0] by b[n], because the step marked (*) above is redundant: the value assigned there is never read before it is reassigned.
I'm a little confused about the result of the following code:
int x = 1;
x -= ((x += 1) << 1);
System.out.println(x);
It prints out -3, but I'd expected it to print out -2, because in my head the computation should go like this:
| Opearation | Returned | x |
+------------+----------+---+
| int x = 1; | - | 1 |
+------------+----------+---+
| (x += 1) | 2 | 2 |
+------------+----------+---+
| (2 << 1) | 4 | 2 |
+------------+----------+---+
| x -= 4; | - |-2 |
What am I missing here? Can somebody please explain to me what's going on?
Thanks!
JLS 15.26.2 says following, https://docs.oracle.com/javase/specs/jls/se9/html/jls-15.html#jls-15.26.2
If the left-hand operand expression is not an array access expression, then:
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.
So the original value of x, i.e. 1, is saved, then the RHS is evaluated. Therefore it's -3.
Unlike some other languages (looking at you, C++), the Java Language Specification guarantees that expression operands are evaluated left-to-right:
The Java programming language guarantees that the operands of operators appear to be evaluated in a specific evaluation order, namely, from left to right.
Let's unroll your compound statement:
x -= ((x += 1) << 1);
x = x - ((x = x + 1) << 1);
^
The x with the arrow is evaluated first, which means that the assignment that happens later within the expression doesn't affect the value (in this case, the JVM stack already has a 1 on it). The rest of the evaluation proceeds as you expect, but the final operation is 1 - 4 = -3.
Note that right after the statement above, the JLS also includes a note that absolutely applies here:
It is recommended that code not rely crucially on this specification. Code is usually clearer when each expression contains at most one side effect, as its outermost operation, and when code does not depend on exactly which exception arises as a consequence of the left-to-right evaluation of expressions.
Value of x (=1) is populated on the RHS of the expression before the sub-expression (x+=1) is processed hence leftmost x is substituted as 1 way before it is processed in x+=1 which results into 2. Hence it will be ...
x = 1 - ((x=1+1) << 1)
x = 1 - ((x=2) << 1)
x = 1 - (2 << 1)
x = 1 - 4
x = -3
Here x=2 results into 2 as assignment operator returns same value as assigned to the variable.
x -= ((x += 1) << 1);
x = x - ((x += 1) << 1);
= 1 - ((1 + 1) << 1);
= 1 - (2 << 1)
= 1 - 4
= -3
I've seen this question in OCA questions and need to know why it outputs 90 and not 100.
Here is the code:
int x = 9;
long y = x * (long) (++x);
System.out.println(y);
So, what I think this would do is, firstly, increment x (because that's what happens at first right?) and then it would do the type promotion and take left x which is 10, turn it into long and multiply those two longs. Right?
No. The operands of each operator are evaluated from left to right. Therefore the first operand of the * operator, x, is evaluated before the second operand (long) (++x). Therefore 9 is multiplied by 10.
From page 280 of OCP Java SE 6 Programmer Practice Exams, question 9:
int x = 3;
x = x++;
// x is still 3
In the explanation we can read that:
The x = x++; line doesn't leave x == 4 because the ++ is applied
after the assignment has occurred.
I agree that x is 3, I understand post-incremenation.
I don't agree with the explanation. I would replace "after" with "before".
I thought it works like this:
x is 3.
x++ is executed. I see this post-increment operator as a function:
int operator++() {
int temp = getX();
setX(temp + 1);
return temp;
}
So, after x++ execution, x is 4, but the value returned from x++ expression is 3.
Now, the assignment =. Simply write returned 3 to x.
So, in my eyes ++ is applied before the assignment has occurred. Am I wrong?
...the ++ is applied after the assignment has occurred.
Okay, hold on. This is actually confusing and perhaps suggests an incorrect behavior.
You have the expression†:
x = ( x++ )
What happens is (JLS 15.26.1):
The expression on the left-hand side of the assignment x is evaluated (to produce a variable).
The expression on the right-hand side of the assignment ( x++ ) is evaluated (to produce a value).
The evaluation of the right-hand side is: x is post-incremented, and the result of the expression is the old value of x.
The variable on the left-hand side, x, is assigned the value produced by the evaluation of the right-hand side, which is the old value of x.
So the post-increment happens before the assignment.
(Therefore, as we know, the value of x after executing the statement x = x++; is the same as the value of x before executing the statement, which is 3.)
So, in my eyes ++ is applied before the assignment has occurred. Am I wrong?
You are right.
Technically, the way it is specified is that x++ is evaluated before its result is stored and during the evaluation of the assignment operator. So x++ can be interpreted as happening either before or during the assignment. Not after, so the book appears to be wrong either way.
Just for the heck of it, we may also look at some bytecode:
/* int x = 3; */
iconst_3 // push the constant 3 on to the stack : temp = 3
istore_0 // pop the stack and store in local variable 0 : x = temp
/* x = x++; */
iload_0 // push local variable 0 on to the stack : temp = x
iinc 0 1 // increment local variable 0 by 1 : x = x + 1
istore_0 // pop the stack and store in local variable 0 : x = temp
The iinc happens before the istore.
†: The parentheses have no effect on the evaluation, they are just there for clarity.
Reaching over to the official spec:
postfix ++ section: https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.14.2
assignment operator section: https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.26.1
In terms of assignment, this is simple assignment, so we hit case 3:
First, the left-hand operand is evaluated to produce a variable -- x
no errors -> the right-hand operand is evaluated -- x++
"the value of the right-hand operand is converted to the type of the left-hand variable, is 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"
So in step 2, the postfix operator should get resolved, and then in step 3, x gets assigned its original value again:
call: x = x++;
interframe: LHS is variable 'x'
interframe: RHS caches return value as 3
interframe: x is incremented to 4
interframe: RHS cached value '3' is returned for assignment
interframe: variable x is assigned value 3
call result: x = 3
So I think you're right in that the book is wrong, and it might be worth contacting the authors or publisher to have a correction published (or added to an errata page, etc)
x++ means "use x and then increment x."
You can also use ++x, which means "increment x and then use x."
More easily, however, you can simply do
x += 1;
++x is called preincrement while x++ is called postincrement.
int x = 3;
x = ++x;
exemple
int x = 5, y = 5;
System.out.println(++x); // outputs 6
System.out.println(x); // outputs 6
System.out.println(y++); // outputs 5
System.out.println(y); // outputs 6