Java vs C output - java

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)...

Related

How to evaluate the java operators evaluation

I am java newbie and trying to understand how calculation steps are performed to achieve final result. The final answer is coming as 49. Looking at precedence operators hierarchy my calculation is not coming to 49.
Following is my code with expression:
class Test
{
public static void main(String args[])
{
int a = 6, b = 5;
a = a + a++ % b++ *a + b++ * --b;
System.out.print(a)
}
}
Modulo has same precedence as division and multiplication. The next precedence goes to addition and subtraction.Operations happen left to right.
Adding brackets for better clarity:
( a ) + ( a++ % b++ *a ) + ( b++ * --b )
group I II III
a++ % b++ *a evaluated as :a. (6 % 5) = 1
b. 1 * 6 till now, a = 6, b = 5
Having completed this operation, the value of a & b are incremented to 7 & 6 respectively. i.e the post fix increment happens only after the modulo/multiplication/division during a step or group as shown above.
b++ * --b => 6 * 6. gives value of 36
Having completed this operation the ++ operation is performed but -- is also performed, effectively leaving the value of b at 6.
next operation is addition. i.e 7 + 6 + 36 = 49
Reference: https://www.programiz.com/java-programming/operator-precedence
Operators have priorities. There is a table of these here.
Also, you can use round brackets (parentheses) for forcing the right sequence of calculations.

Java expressions calculation precedence: method invocation & array indexing

During the study of java expression calculation order I faced with one phenomenon I can't explain to myself clearly. There are two quiz questions. It is asked to define the console output.
Example 1
int[] a = {5, 5};
int b = 1;
a[b] = b = 0;
System.out.println(Arrays.toString(a));
Correct console output is: [5,0]
Example 2
public class MainClass {
static int f1(int i) {
System.out.print(i + ",");
return 0;
}
public static void main(String[] args) {
int i = 0;
i = i++ + f1(i);
System.out.print(i);
}
}
Correct console output is: 1,0
As I learned, there is operators groups (levels) with ordered precedence in java and expressions are evaluated according to operator precedence. Also there is associativity of each group and if operators have the same precedence, then they are evaluated in order specified by group associativity. The operators precedence table (from Cay S. Horstmann - Core Java V.1):
# operator associativity
1 [] . () method call left to right
2 ! ~ ++ -- + - (type) cast new right to left
3 * / % left to right
4 + - left to right
...
14 = += -= the rest are omitted right to left
With the table above it's become clear that in example 1 the operator with highest priority is array indexing a[b] and then аssignment operators are evaluated from right to left: b=0, then a[1]=0. That is why a=[5,0].
But the example 2 confuses me. According to the precedence table, the operator with highest priority is f1(i) method invocation (which should print 0), then unary post-increment i++ (which uses current i=0 and increments it after), then addition operator 0+0 and аssignment operator finally i=0. So, I supposed the correct output is 0,0.
But in fact it is not. In fact the unary post-increment i++ is calculated first (increasing i to 1), then method invocation f1(i) prints 1 and returns 0 and finally аssignment operator assigns i=0+0, so the final i value is 0 and correct answer is 1,0.
I suppose this is so due to binary addition operator associativity "from left to right", but in this case why do addition is calculated first in example 2, but in example 1 the highest priority operator a[b] is calculated first? I noticed that all operators in example 2 are in different groups, so we shouldn't take operator associativity into consideration at all, should we? Shouldn't we just order all operators from example 2 by precedence and evaluate it in resulting order?
You are confusing evaluation order with precedence.
The right-to-left associativity of = means that
a[b] = b = 0;
is evaluated as
a[b] = (b = 0);
but the evaluation is still left-to-right, so the value of the first b is evaluated before the value of b is updated.
a[b] = (b = 0) a = { 5, 5 }, b = 1
// evaluate 'b'
a[1] = (b = 0) a = { 5, 5 }, b = 1
// evaluate 'b = 0'
a[1] = 0 a = { 5, 5 }, b = 0
// evaluate 'a[1] = 0'
0 a = { 5, 0 }, b = 0
Operator presendence and associativity affect how source code is parsed into an expression tree. But : evaluation order in any expression is still left-to-right.
That's why in i++ + f1(i), we first evaluate i++, then f1(i), and then compute their sum.
Method call having the highest priority means that i++ + f1(i) will never be parsed as (i++ + f1)(i) (if that even makes sense), but always i++ + (f1(i)). Priority does not mean "is evaluated before anything else."

Java Arithmetic expression

The following expression evaluates to 14.
int a=4;
int b=6;
int c=1;
int ans= ++c + b % a - (c - b * c);
System.out.print(ans);
This is how i calculate this
1. (c - b * c) // since bracket has highest preference
ans : -5
2. ++c //since unary operator has next highest preference
ans : 2
3. b%a // % has higher preference than + and -
ans : 2
Therefore, 2 + 2 - (-5) = 9
As you can see I'm getting 9 as the value. Not sure what's wrong in my way of calculation (pretty sure I'm gonna end up looking stupid)
Edit : I refered to the below link for precedence and association.
https://introcs.cs.princeton.edu/java/11precedence/
Can someone explain the difference between level 16 and level 13 parentheses? I thought level 13 parentheses is used only for typecasting. That is why i considered level 16 parenthesis for evaluating the expression.
Evaluation order is not the same as precedence. Java always evaluates left-to-right (with a minor caveat around array accesses).
Effectively, you are evaluating the following expression, because the very first thing that happens is the pre-increment of c:
2 + 6 % 4 - (2 - 6 * 2)
Precedence then describes how the values are combined.
As you are using pre-increment operator on c. So, after applying increment on c the value of c will be 2. Now :
(c - b * c) will be evaluated to (2 - 6 * 2)= -10
So, the final expression will be 2 + 2 - (-10) = 14

Result of function that includes pre- and post-increment differs

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.

Operator Precedence and associativity

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.

Categories

Resources