I have two similar questions about operator precedences in Java.
First one:
int X = 10;
System.out.println(X++ * ++X * X++); //it prints 1440
According to Oracle tutorial:
postfix (expr++, expr--) operators have higher precedence than prefix (++expr, --expr)
So, I suppose that evaluation order:
1) first postfix operator: X++
1.a) X++ "replaced" by 10
1.b) X incremented by one: 10+1=11
At this step it should look like: System.out.println(10 * ++X * X++), X = 11;
2) second POSTfix operator: X++
2.a) X++ "replaced" by 11
2.b) X incremented by one: 11+1=12
At this step it should look like: System.out.println(10 * ++X * 11), X = 12;
3) prefix operator: ++X
3.a) X incremented by one: 12+1=13
3.b) ++X "replaced" by 13
At this step it should look like: System.out.println(10 * 13 * 11), X = 13;
4) evaluating 10*13 = 130, 130*11 = 1430.
But Java seems to ignore PRE/POST ordering and puts them on one level. So the real order:
X++ -> ++X -> X++
what causes the answer to be (10 * 12 * 12) = 1440.
Second one:
Example from this question:
int a=1, b=2;
a = b + a++;
Part of accepted answer:
"By the time of assignment, ++ has already incremented the value of a to 2 (because of precedence), so = overwrites that incremented value."
OK, let's look step-by-step:
1) replacing "b" with 2
2) replacing "a++" with 1
3) incrementing "a" by 1 -> at this point a==2
4) evaluating 2+1 = 3
5) overwriting incremented value of "a" with 3
Seems everything is fine.
But let's make a little change in that code (replace "=" with "+=")
a += b + a++;
steps 1-4 should be same as above.
so, after step 4 we have something like that:
a += 3;
where a==2
And then I think: OK, a = 2+3, so a should be 5. BUT the answer is only 4
I'm really confused. I already spent couple of hours but still can't understand where I am wrong.
P.S. I know, that I shouldn't use this "style" in real applications. I just want to understand what is wrong in my thoughts.
The confusion stems from the fact that the operands are evaluated from left to right. This is done first, before any attention is paid to operator precedence/order of operations.
This behavior is specified in JLS 15.7.2. Evaluate Operands before Operation
So X++ * ++X * X++ is first evaluated as 10 * 12 * 12 which yields, as you saw, 1440.
To convince yourself of this, consider the following:
X = 10; System.out.println(X++ * ++X);
X = 10; System.out.println(++X * X++);
If X++ were done first, then ++X second, then multiplication, both should print the same number.
But they do not:
X = 10; System.out.println(X++ * ++X); // 120
X = 10; System.out.println(++X * X++); // 121
So how does this make sense? Well if we realize that operands are evaluated from left to right, then it makes perfect sense.
X = 10; System.out.println(X++ * ++X); // 120 (10 * 12)
X = 10; System.out.println(++X * X++); // 121 (11 * 11)
The first line looks like
X++ * ++X
10 (X=11) * (X=12) 12
10 * 12 = 120
and the second
++X * X++
(X=11) 11 * 11 (X=12)
11 * 11 = 121
So why are prefix and postfix increment/decrement operators in the table?
It is true that increment and decrement must be performed before multiplication. But what that is saying is that:
Y = A * B++
// Should be interpreted as
Y = A * (B++)
// and not
Y = (A * B)++
Just as
Y = A + B * C
// Should be interpreted as
Y = A + (B * C)
// and not
Y = (A + B) * C
It remains that the order of the evaluation of the operands occurs left-to-right.
If you're still not conviced:
Consider the following program:
class Test
{
public static int a(){ System.out.println("a"); return 2; }
public static int b(){ System.out.println("b"); return 3; }
public static int c(){ System.out.println("c"); return 4; }
public static void main(String[] args)
{
System.out.println(a() + b() * c());
// Lets make it even more explicit
System.out.println(a() + (b() * c()));
}
}
If the arguments were evaluated at the time they were needed, either b or c would come first, the other next, and lastly a. However, the program outputs:
a
b
c
14
a
b
c
14
Because, regardless of the order that they're needed and used in the equation, they're still evaluated left to right.
Helpful reading:
What are the rules for evaluation order in Java?
a += a++ * a++ * a++ in Java. How does it get evaluated?
Appendix A: Operator Precedence in Java
In short,
Precedence is like preparing the expression to be calculated by putting parentheses. Evaluation comes next from left to right considering each pair of parentheses as a separate operation.
For example,if i=2 then i+i++ becomes i+(i++) after precedence and evaluates to 2+2 = 4.
However, i+++i becomes (i++)+i and evaluates to 2+3 = 5.
Same to i+(i=5) which evaluates to 2+5 = 7.
In fact the postfix operators do have higher precedence than prefix operators. For example, i+++++i becomes ((i++)++)+i after precedence which gives a compile error (the second postfix operator needs a variable to operate on but a value is found instead!). If both postfix and prefix operators had had equal precedence then the expression would have become (i++)+(++i) and evaluates to 2+4 = 6.
If you need more explanation you can compile and run the following code and inspect the examples printed at the output.
public class TestPrecedence {
public static void main(String[] str) {
int i = 0;
System.out.println("\n");
i = 2; System.out.println("i = " + i + "\n");
i = 2; System.out.println("i++ = " + i++ + "\n");
i = 2; System.out.println("++i = " + ++i + "\n");
i = 2; System.out.println("i++i = (i++)i TestPrecedence.java:8: error: ')' expected\n"+
" i++i\n"+
" ^\n");
i = 2; System.out.println("i+-i = i+(-i) = " + (i+-i) + "\n");
i = 2; System.out.println("++i++ = ++(i++) TestPrecedence.java:12: error: unexpected type\n"+
" ++i++ \n"+
" ^\n"+
" required: variable\n"+
" found: value\n");
i = 2; System.out.println("i+++++i = ((i++)++)+i TestPrecedence.java:17: error: unexpected type\n"+
" i+++++i\n"+
" ^\n"+
" required: variable\n"+
" found: value\n");
i = 2; System.out.println("i++ + ++i = " + (i++ + ++i) + "\n");
i = 2; System.out.println("i+(i=3) = " + (i+(i=3)) + " evaluates left to right\n");
i = 2; System.out.println("i+i++ precedence yields i+(i++) evaluates to 2+2 = " + (i+i++) + "\n");
i = 2; System.out.println("i+++i precedence yields (i++)+i evaluates to 2+3 = " + (i+++i) + "\n");
System.out.println("\n");
}
}
The reason why its 1440 is because
x is set to 10 i.e 1st term is FIXED(overall equation 10 *)
x is incremented by 1,x =11 now
x is pre-incremented by 1 x=12 and second term FIXED now (overall equation 10 * 12 *)
now x is set to 12 and third term FIXED(overall equation 10 * 12 *12)
x is increment now but is in this case not used for evaluation,
in short a term is FIXED when variable occurs which in this case is X
2nd case:
I'm not sure but I guess can be broken as,
a=b+a
a++
which I think is what is happening.
For the second one ->
int a=1, b=2;
a += b + a++;
Compiler will convert it to
a = a + b + a++;
Then apply your logic and you will find the reason why a is 4.
First step
1) first postfix operator: X++
1.a) X++ "replaced" by 10
1.b) X incremented by one: 10+1=11
At this step it should look like: System.out.println(10 * ++X * X++), X = 11;
2) prefix operator: ++X
2.a) X "replaced" by 11
2.b) X incremented by one: 11+1=12
At this step it should look like: System.out.println(10 * 12 * X++), X = 12;
3) second POSTfix operator: X++
3.a) X "replaced" by 12
3.b) X incremented by one: 12+1=13
At this step it should look like: System.out.println(10 * 12 * 12), X = 13;
This prints 10 * 12 * 12 = 1440
This is the bytecode for the first step
1. bipush 10
2. istore_0
3. getstatic java/lang/System/out Ljava/io/PrintStream;
4. iload_0
5. iinc 0 1
6. iinc 0 1
7. iload_0
8. imul
9. iload_0
10. iinc 0 1
11. imul
12. invokevirtual java/io/PrintStream/println(I)V
13. return
This do the following:
1. Push 10 to the stack
2. Pop 10 from the stack to X variable
3. Push X variable value (10) to the stack
5. Increment local variable X (11)
6. Increment local variable X (12)
7. Push X variable value (12) to the stack
8. Multiply top and subtop (10*12) Now Top = 120
9. Push X variable value (12) to the stack
10. Increment local variable X (13)
11. Multiply top and subtop (120*12) Now Top = 1440
Notice than the last increment (10.) is done after the push of X to the stack
Related
i have problem to step by step java expression calculation
System.out.println(++x + x++ * y-- - --y);
I know this precedence:
1. postfix unary
2. prefix unary
3. multiplicative
4. additive
but when i calculate with this precedence the result is below:
// 12 + 11 * 19 - 18
can some one help me
You can understand it from the example given below:
public class Main {
public static void main(String[] args) {
int x = 5, y = 10;
System.out.println(++x + x++ * y-- - --y);// 6 + 6 * 10 - 8 = 58
}
}
Steps in this calculation:
++x = 6
6 + x++ * y-- = 6 + 6 * 10 = 6 + 60 = 66 (after this y will become 9 because of y-- and x will become 7 because of x++ but this increased value of x has never been used in subsequent calculation)
66 - 8 = 58 (before y gets subtracted from 66, it will become 8 because of --y)
Postfix unary is applied after the variable evaluation, opposite to prefix, which is applied before evaluation, your expression can be rewrited:
int x_prefix = x + 1; // ++x
int y_prefix = y - 1; // --y
System.out.println(x_prefix + x * y - y_prefix);
int x = x + 1; // x++
int y = y - 1; // y--
You write operators precedence, it's right but every operator has own behavior, in case of postfix increment, of course has to be evaluate before others, but its behavior is return the current variable and after increment its value.
NOTE: I just rewrited your expression as is, if you use in the same expression the variable postfix incremented, the next access see the variable incremented:
int x = 1;
System.out.println(x++ + x++); // 1 + 2
System.out.println(x) // 3
For completeness:
int x = 1;
System.out.println(++x + ++x); // 2 + 3
System.out.println(x) // 3
Operator precedence of ++ and -- is higher than + and has associativity right to left. So I think output of x should be (++i+4 then 5+4) 9 and output of y should be (i+++5 then 5+5) 10. For both it print 11 as output.
class First {
public static void main(String[] args) {
int i = 5;
int x = ++i + --i;
int y = i++ + i--;
System.out.println("x="+x);
System.out.println("y="+y);
}
}
Let's translate this:
int i = 5;
int x = ++i + --i;
int y = i++ + i--;
System.out.println("x=" + x);
System.out.println("y=" + y);
Into (step by step):
int i = 5;
int x = ++i + --i;
// ^
// (i = i + 1) + --i
// (i = 5 + 1) + --i
// (i = 6) + --i
// ^
// 6 + (i = i - 1)
// 6 + (i = 6 - 1)
// 6 + (i = 5)
// 6 + 5
// x = 11
int y = i++ + i--;
// ^
// (i = 5) + i--
// 5 + i--
// i = i + 1 // post evaluation, after i was evaluated to 5, now i increments its value and it is 6
// 5 + (i = 6)
// 5 + 6
// y = 11
// i = i - 1 // post evaluation, after i was evaluated to 6, now i decrements its value and it is 5
System.out.println("x=" + x); // x=11
System.out.println("y=" + y); // y=11
Section 15.7 of the JLS is clear on this:
The Java programming language guarantees that the operands of operators appear to be evaluated in a specific evaluation order, namely, from left to right.
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.
Whenever assignment operators and other binary operators are mixed in with increment or decrement operators, evaluating the expression is not intuitive, and one should never write such confusing code.
Even if the increment and decrement unary operators are right-to-left associative, the values of an expression are evaluated left-to-right.
int x = ++i + --i;
Here, ++i increments i to 6 and returns 6, then --i decrements i to 5 and returns 5, and the sum of 6 and 5 is 11.
int y = i++ + i--;
Here, i++ returns 5 and increments i to 6, then i-- returns 6 and decrements i to 5, and the sum of 5 and 6 is 11.
With these expressions, the right-to-left associativity does not figure into the order of operations, because associativity only controls which operations are executed first among operators of the same precedence. You have a + operator of lower precedence between them, so the associativity doesn't matter here.
Associativity dictates how operators with the same precedence are parsed.
For example, the Unary Minus (- ...) and Unary Bitwise NOT (~ ...) operators have the same precedence and have right-to-left associativity. Therefore:
int i = ~-1; // == 0
int j = -~1; // == 2
I was give the following snippet of code to help me with a problem that involves the palindrome of a number. I am at a loss to figure out how this works exactly. I understand that it involves the while loop but am unable to follow the logic.
public static boolean isPalindrome(int nr) {
int rev = 0;
int x = nr;
while (x > 0) {
rev = 10 * rev + x % 10;
x /= 10;
}
return rev == nr;
}
Can someone please explain how this works?
If the number is a palindrome, then rev will equal the number after the loop finishes. Here's how it works, with a sample iteration where nr is 121:
public static boolean isPalindrome(int nr) {
int rev = 0;
int x = nr; // 121
while (x > 0) {
rev = 10 * rev + x % 10; // x % 10 is the last digit of x when in base 10. multiplying the previous value of rev by 10 and adding x % 10 is adding the last digit of x to the next digit of rev
// step 1: rev = 10*0 + 1 = 1
// step 2: rev = 10*1 + 2 = 12
// step 3: rev = 10*12 + 1 = 121
x /= 10; // truncates the last digit of x
}
so the return statement should be return rev == nr;
A palindrome is a number which reads same whether you read it from left to right or from right to left.
For Example - 1221
Now the execution
Suppose you have entered 1221 as the number.
Your calling method statement will look like
isPalindrome(1221);
Step 1 - Here we have three variables nr = 1221 , rev = 0 and x which will hold the original value which is 1221.
As soon as while loop begins it checks whether x is greater than zero or not, in our case 1221 is greater than 0 which is true so the program will go inside the loop.
Then rev = 10 * rev + x % 10;
This expression will change the initial value of rev which is zero.
10* 0 + 1221 % 10 will give 1 as the answer. since % modulus operator gives the remainder so 1221 when divided by 10 will give 1 as the remainder.
Now rev has 1 as its value.
Program will go to next statement to update the value of x as we have already stored one digit of our palindrome entry.
x / = 10 ;
This is a shorthand statement which is equivalent to
x = x / 10;
So here when x is divided by 10 we will get 122 as the quotient and 122 will be stored in x.
Step 2 - Now program flow will agin go to the first statement, ( thats the beauty of loops) to check for the condition whicha gain willl be true as x = 122 is greater than 0.
and now the value of rev will be
rev = 10 * 1 ( remember value of rev is 1 at the moment) + 122% 10 ;
the new value of rev will be
rev = 10 * 1 + 2 ( since modulus or remainder of 122 when divided by 10 is 2 )
final value according to first statement would be
rev = 12.
and program will be ahead to change the value of x since we are done with last two digit of our entered number.
x = x / 10; which will result us the quotient of 12.
Step 3 - 12 is greater than 0 condition true program will move to next statement.
rev = 10 * rev (12) + x (12) % 10;
new rev value
rev = 120 + 2 ;
rev = 122
the next statement will give us another changed value of x so that we can complete our palindrome digit.
x = x / 10;
x = 12/10; will give us 1 as quotient
Step 4 - while condition will again be satisfied which is 1 is greater than 0
and the updated rev value would be
rev = 10* rev (122) + 1% 10;
since diving 1 with ten will give us the remainder 1 , so the final expression will be
rev = 1221
and now the last change is value of x
x = x(1) \ 10 ;
x will be zero as there will be no quotient when dividing 1 with ten.
Step 5- 0 is greater than 0 condition will be false and program will exit the while and the final values of all the variables will be
nr = 1221
rev = 1221
x = 0
few statements inside your method will justify the return type Boolean.
if(nr==rev)
return true ;
else
return false;
I hope I could explain you the flow, also would like you to dry run the same program for non palindrome digit.
Original fragment of code when input parameter nr (later x, x>0) makes two things:
public static boolean isPalindrome(int nr) {
int rev = 0;
int x = nr;
while (x > 0) {
rev = 10 * rev + x % 10; // impl., for examp. 13 / 10 = 1
x /= 10; // f truncation of x
}
Sorry, I couldn't think of a better title.
Anyway, when I compile the following code:
class Example{
public static void main(String[] args) throws Exception {
int x = 3;
x -= 2 + x++ == 4 ? x++ : ++x;
System.out.println("x = " + x);
}
}
I get the answer -2.
Now I would really like to know how it comes to this answer, as I can't find it.
It would be amazing if I could get an answer to this, as this may be on a exam that I'll have somewhat soon.
Note: Of course I wouldn't ever code out something like this myself, this is just an exercise.
Thanks so much if you can help me out!
Edit: answer to fge's answer:
Okay, thanks! but now if I change it up a little and make it like so:
x = 2;
x += 3 + ++x == 6 ? x-- : x--;
System.out.println("x = " + x);
I would think that you would get the following:
++x == 6
is not true, as x is now 3. this means we get x--, making it now 2 again.
then we get 3 + 2 = 5, so the expression can be evaluated to:
x += 5
because x is now 2, we get 2 + 5 = 7.
When you create such code example
int x = 3;
System.out.println(2 + x++ == 4 ? x++ : ++x);
you will see that the output is 5. It is because it is equivalent to
(2 + x++) == 4 ? x++ : ++x
so first Java will evaluate (2+ x++). Since we have x++ value of x will be returned first creating (2+3) and then incremented, so x will be now 4 after it.
Since (2+3) == 4 is false because (5 == 4) we will execute this part ++x, first incrementing x to 5 and then returning it.
Now lets go back to your example
int x = 3;
x -= 2 + x++ == 4 ? x++ : ++x;
You may know that x -= y is in fact x = x - y so it can be written as
x = x - (2 + x++ == 4 ? x++ : ++x);
So, since Java evaluates from left to right it will be
x = 3 - (2 + x++ == 4 ? x++ : ++x);
We know now that (2 + x++ == 4 ? x++ : ++x) is in fact 5 so
x = 3 - 5; // == -2
int x = 10;
x += x++;
System.out.println(x);
why the answer of above statement is 20 ?
The operator += is an addition assignment operator. Like Alya said above, x += x++ is equivalent to x = x + x++, which in your case is x = 10 + 10. However, it's a very messy statement and I'll explain why towards the end of this post.
Now, you're probably thinking "Why is it 20 and not 21 (10 + 11) since you have the ++?" and that's valid. There's actually a difference between a post-increment and a pre-increment. x++ is the post-increment and will actually evaluate the value of x first and THEN increment x, while ++x is the pre-increment which will increment x and THEN evaluate the value of x.
For example, x = 10; System.out.println(x++); System.out.println(x); will print 10 and then print 11 because the first print line prints x and THEN performs the ++ calculation, making x 11 which the next line prints. Conversely, x = 10; System.out.println(++x); System.out.println(x); will print 11 on both print statements.
Going back to why I said x += x++; is very messy is because technically the ++ operator isn't performed in this case. x++ is technically the same as x=x+1 and remembering that x+=y is the same as x = x+y) , the line x += x++; is kind of like saying x = x + (x = x + 1); which is kind of weird looking because you do 2 assignment statements in one and won't actually "work how you want it". Back to your example int x = 10; x += x++; if you print x, you will get 20 even though you could look at it as: x is now the value of x + the value of x, then finally + 1 to it. But unfortunately, that's not how it works.
To solve your problem, if you change your code from a post-increment to a pre-increment, then it should work, ie: x+=++x; will print your 11 but I would argue the that's quite unreadable and a bit confusing. x+=x; x++; System.out.println(x); is easier to follow.
x++ will execute first. It returns x and then increments x by 1.
Finally, the += operator will add to x the return value of x++, which was 10.
Thus, x will be 20 and it will overwrite the changes to x by the statement x++.
So first x is initialized to be 10. Then the x++ has higher precedence so that gets carried out first. the "++" is a post-increment in this case (because it is after the variable as opposed to pre-increment which would be ++x). Post-increment means "first use the variable then increment it by one" so in this case it first uses x to be 10 then increments it to 11 after it is used. Then we look at the "+=" which is short hand for "x = x+x++". so we have x = 10+10 which = 20. If you were to carry this out again it would equal x = 20+20 = 40.
In this particular case, the x++ isn't necessary as x is reassigned the value after it is incremented each time.
int x = 10; x += x++;
will equal to x=x+x
where x++ mean use the x value then increament it , so it's value will be 10
so the result will equal 20
if you want to see the change of the x , see this example:
int x = 10;
int y = 10;
y +=x++;
System.out.println(y);
System.out.println(x);
will print :
y=20
x=11////////////according to x++ and without to overwrite it
//
// Shows how increments work.
//
int i = 0;
System.out.println(i);
i++; // Add one
System.out.println(i);
i += 2; // Add two
System.out.println(i);
i += 3; // Add three
System.out.println(i);
++i; // Add one
System.out.println(i);
i += i; // Added itself
System.out.println(i);
//
// Uses increments and assigns.
//
int v = 0;
v = i++; // Increment after value copy
System.out.println(v);
System.out.println(i);
v = ++i; // Increment before value copy
System.out.println(v);
System.out.println(i);
//Output
0 -
1
3
6
7
14
14
15
16
16
x+=x++ first assigns the value to x and then increments (post-increment)
x+=++x first increments then assign the value to x (pre increment)
there are two types of increments/decrements in programming
1. pre-increment/decrement
2. post-increment/decrement
In programming both of these have same operations but differ in there nature as they both used for increment or decrement; they can be written as,
x+=1; (increment by 1)
x-=1; (decrement by 1)
you can use a variable instead in the above cases as well