Can anyone explain me how different spacing affects the unary operator?
int i = 1;
int j = i+ + +i; // this will print j=2
int k = i++ +i; // this will print k=3
int l = i+++i; // this will print l=3
int m = i++++i; // compile time error
.
First, let's separate this into three separate cases which can't interact:
int i = 1;
System.out.println(i+ + +i); // 2
int j = 1;
System.out.println(j++ +j); // 3
int k = 1;
System.out.println(k+++k); // 3
Now let's rewrite them using brackets:
int i = 1;
System.out.println(i + (+(+i)));
int j = 1;
System.out.println((j++) + j);
int k = 1;
System.out.println((k++) + k);
First operation
Here we can't be using the prefix or postfix ++ operators, as we don't have a token of ++ anywhere. Instead, we have a binary + operator and two unary + operators.
Second operation
This one's simple: it's pretty much as it reads, a postfix ++ operator followed by a binary + operator (not the unary + operator that +j might otherwise imply).
Third operation
The final line is parsed as (k++) + k rather than k + (++k). Both will actually give the same answer in this situation, but we can prove which is which by using two different variables instead:
int k1 = 1;
int k2 = 1;
System.out.println(k1+++k2); // Prints 2
System.out.println(k1); // Prints 2
System.out.println(k2); // Prints 1
As you can see, it's k1 that's been incremented rather than k2.
The reason that k+++k is parsed as tokens of k, ++, +, k is due to section 3.2 of the JLS, which includes:
The longest possible translation is used at each step, even if the result does not ultimately make a correct program while another lexical translation would.
Fourth operation (compile failure)
The same "longest possible translation" rule parses i++++i as i, ++ ,++, i which isn't a valid expression (because the result of the ++ operation is a value, not a variable).
+ is an operator, and ++ is an operator, but + + is not - + + is interpreted as two +s, not one ++. So the space forces your code to be interpreted differently.
+ is both a binary operator which adds two numbers and a unary operator which does not change a number (it exists only for consistency with the unary - operator).
If we use add instead of binary +, no-change instead of unary +, and increment instead of ++ then it might be more clear.
int j=i+ + +i becomes int j = i add no-change no-change i;.
int k=i++ +i; becomes int k=i increment add i;.
I suspect int k = i+++i; also becomes int k = i increment add i; but I have not checked this with the language specification.
Related
for(int i = 1; i <= 5; i++) {
for(int j = 1; j <= i; j++) {
int a = i + j*2;
System.out.print(a);
}
}
when run the above code I am getting output as
3
46
579
681012
79111315
I am not able to understand why it is printing first row as 3, i+j*2 =4 as per the logic.
I am not able to understand why it is printing first row as 3, i+j*2 =4 as per the logic.
Precedence. Multiplication takes precedence over addition, so on the first call, i+j*2 is 1+1*2 which is 1+(1*2) which is 1+2 which is 3.
The precedence of basic operations can be remembered with PEMDAS or BODMAS (the "MD" and "AS" have the same precedence, so I've shown them on a single line here):
P Parentheses / Brackets B
E Exponenentiation / Orders1 O
MD Multiplication & Division DM
AS Addition and Subtraction AS
1 Powers (2^5), square roots, etc.
The Java site has a page on operator precedence, which has this table:
postfix expr++ expr--
unary ++expr --expr +expr -expr ~ !
multiplicative * / %
additive + -
shift << >> >>>
relational < > <= >= instanceof
equality == !=
bitwise AND &
bitwise exclusive OR ^
bitwise inclusive OR |
logical AND &&
logical OR ||
ternary1 ? :
assignment = += -= *= /= %= &= ^= |= <<= >>= >>>=
1 They mean the conditional operator, which is a ternary operator (an operator accepting three operands) and as it happens, the only one Java has.
Multiplication (*) has arithmetic precedence over addition (+). In the first iteration, i and j are both 1. The first thing to be calculated is j*2, i.e., 1*2=2. Then we add i and the previously calculated product and get 1+2=3.
This question already has answers here:
How to evaluate a math expression given in string form?
(26 answers)
Closed 7 years ago.
I am trying to write a program in Java which takes input a String value
like s = "1+27-63*5/3+2" and returns the calculation in integer value
Here below is my code
package numberofcharacters;
import java.util.ArrayList;
public class App {
public static void main(String[] args) {
String toCalculate = "123+98-79÷2*5";
int operator_count = 0;
ArrayList<Character> operators = new ArrayList<>();
for (int i=0; i < toCalculate.length(); i++){
if (toCalculate.charAt(i) == '+' || toCalculate.charAt(i) == '-' ||
toCalculate.charAt(i) == '*' || toCalculate.charAt(i) == '÷' ) {
operator_count++; /*Calculating
number of operators in a String toCalculate
*/
operators.add(toCalculate.charAt(i)); /* Adding that operator to
ArrayList*/
}
}
System.out.println("");
System.out.println("Return Value :" );
String[] retval = toCalculate.split("\\+|\\-|\\*|\\÷", operator_count + 1);
int num1 = Integer.parseInt(retval[0]);
int num2 = 0;
int j = 0;
for (int i = 1; i < retval.length; i++) {
num2 = Integer.parseInt(retval[i]);
char operator = operators.get(j);
if (operator == '+') {
num1 = num1 + num2;
}else if(operator == '-'){
num1 = num1 - num2;
}else if(operator == '÷'){
num1 = num1 / num2;
}else{
num1 = num1 * num2;
}
j++;
}
System.out.println(num1); // Prints the result value
}
}
****The problem is I need to perform calculation according to Order of operations in Math like Multiplication and division first , than addition and subtraction.
How can I resolve this? ****
I have used String split() method to seperate the String wherever the operators "+-/*" occurs. I have used character ArrayList to add operators in it.
Than at the last portion of code I am looping in that splitted array of Strings and I've initialize int num1 with the first value of splitted array of strings by parsing it to Integer. and int num2 with the second value and the using operators arraylist to perform calculation between them (whatever the operator at that index of arraylist). and storing the result in int num1 and doing vice versa until the end of the string array.
[P.S] I tried to use Collection.sort but it sorts the above arraylist of operators in that order [*, +, -, /]. It puts division at the end while it should put division after or before multiplication symbol
If you want to do it with roughly the same structure of code, and not turn it into something like reverse Polish notation first, you could try an approach that deals with the operations in reverse priority order.
So assuming that you have * and / as highest precedence, and you're treating them as equal precedence and therefore to be dealt with left-to-right; and the same for + and -; then you would
Split first on + and -.
Evaluate the parts that are separated by + and -, but now processing * and / in left-to-right order.
Apply your + and - to these evaluated parts.
So if your expression is 3*4+5-6/2 then your code would split first into
3*4 + 5 - 6/2
Now evaluate these sub-expressions
12 + 5 - 3
Now process left-to-right to evaluate the final answer
14
In more general terms, the number of passes you'll need through your expression is determined by the number of precedence levels you have; and you need to process the precedence levels from lowest to highest. Split expression up; recursively evaluate sub-expressions just considering next precedence level and upwards; combine to get final answer.
This would be a nice little Java 8 streams exercise!
Confusion rose because of this post. The author updated his post, and the result became clear.
Conclusion: Java evaluates expressions from left to right
Closed!
As evaluation of expression is done from right to left the following code should store 5 in j:
int i=2;
int j=++i+i++;
System.out.println(j);
But I get 6 as the output, which forces me to re-think the right to left evaluation idea. Kindly explain the theory here.
You get 6 because it's 3 + 3:
the first OP is ++i which increments first (to 3) then that value is used
next OP is +i which adds 3 again
last OP ++ doesn't take part in the addition, but it increments i after using it
Your assumption is false. Here's what the documentation says :
All binary operators except for the assignment operators are evaluated
from left to right
So
++i+i++
is equivalent to
(++i)+(i++)
where ++i is evaluated first.
This gives
3+3
which is 6 (and i has value 4 after this).
int i = 2;
int j = ++i + i++;
is the same as
int i = 2;
// This part is from ++i
i = i + 1;
int left = i; // 3
// This part is from i++
int right = i; // 3
i = i + 1;
int j = left + right; // 3 + 3 = 6
If instead you'd done:
int i = 2;
int j = i++ + ++i;
that would be equivalent to:
int i = 2;
// This part is from i++
int left = i; // 2
i = i + 1;
// This part is from ++i
i = i + 1;
int right = i; // 4
int j = left + right; // 2 + 4 = 6
So the sum is the same, but the terms being summed are different.
The first ++ increments i. The + adds i to itself. i is 3.
Where'd you get the idea that it is right-to-left? It is left-to-right.
What are the rules for evaluation order in Java?
This how it works, since unary operators have more precedance than binary:
int i=2;
int j =(++i)+(i++);
^^^ ^^^
3 +(i++) //The value of i is now 3.
^^^ ^^^
3 + 3 //The value of i is incremented after it is assigned.
When evaluating an expression such as a+b, before you can add 'b' to 'a', you need to know what 'a' is. In this case, a is ++i, which is 3, and b is i++ which is 3. Evaluating right-to-left gives 3 + 3 = 6
In Java and C#, the evaluation of subexpressions will be done left to right:
int j=++i + i++;
contains the following two subexpressions ++i and i++. These subexpressions will be evaluated in this order so this will translate into:
int j= 3 + 3;
As in Java and C#, the ++i will be executed returning 3 but i will be changed to 3 before the second i++. The second will return the current value of i which is 3 now and after i++ the value of i will be 4.
In C++ this would be undefined.
And in real-world, you do not want to type this code (except for code golfing)
Take a look at the following code:
class experiment{
public static void main(String[] args) {
int k = 3;
while (k-- > 0) {
System.out.println(k + "\n");
}
}
}
Expected output:
2
1
Actual output:
2
1
0
Postfix operators have higher precedence than operational operators. Hence k-- should be evaluated first before the k > 0, but looking at the output, k > 0 gets evaluated first. Do I miss something simple here?
Precedence has nothing to do with it. The value of 'k--' is 'k'. There is a side-effect of post-decrementing 'k' but it doesn't affect the operand value.
Yeah you are right. k-- will be evaluated first. But it is really evaluated to k. And after the current operation involving it is completed, it's value is increased. So, first the current value is used and then the increment happen.
Had you used --k, you would have got the expected output.
Just try these examples, you will understand: -
int k = 4;
System.out.println(k-- + " : " + k); // prints 4 : 3
int x = 5;
System.out.println(--x + " : " + x); // prints 4 : 4
You're right, the k-- is evaluated before the > 0. However, the result of that evaluation is k, not k - 1, as the -- is post-fix, not pre-fix.
So, the first time the > is evaluated, it is effectively 3 > 0, because although k now is 2, the result of the expression k-- is 3. By the time the print comes around though, k = 2, hence 2 is output first. This is why you get one more iteration than (I guess) you were expecting.
I want to swap the value of two integer variables in java using the XOR operator.
This is my code:
int i = 24;
int j = 17;
i ^= j;
j ^= i;
i ^= j;
System.out.println("i : " + i + "\t j : " + j);
It will work fine but the following equivalent code doesn't work:
int i = 24;
int j = 17;
i ^= j ^= i ^= j;
System.out.println("i : " + i + "\t j : " + j);
Output is like this:
i : 0 j : 24
First variable is zero! What's wrong with Java?
According to Java specification (Java 7 specification), Section 15.26.2 (page 529).
A compound assignment expression of the form E1 op= E2 is equivalent to E1 = (T) ((E1) op (E2)), where T is the type of E1, except that E1 is evaluated only once.
According to Section 15.7 Evaluation Order (Page 423) (emphasis mine):
15.7 Evaluation Order
The Java programming language guarantees that the operands of operators appear to be evaluated in a specific evaluation order, namely, from left to right.
15.7.1 Evaluate Left-Hand Operand First
The left-hand operand of a binary operator appears to be fully evaluated before any part of the right-hand operand is evaluated.
If the operator is a compound-assignment operator (§15.26.2), then evaluation of the left-hand operand includes both remembering the variable that the left-hand operand denotes and fetching and saving that variable's value for use in the implied binary operation.
If evaluation of the left-hand operand of a binary operator completes abruptly, no part of the right-hand operand appears to have been evaluated.
Described in more details in Section 15.26.2 (page 529):
If the left-hand operand expression is not an array access expression, then:
• First, the left-hand operand is evaluated to produce a variable. [trimmed]
• Otherwise, the value of the left-hand operand is saved and then the right-hand operand is evaluated. [trimmed]
• 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. [trimmed]
• 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.
An example in the documentation
Example 15.26.2-2. Value Of Left-Hand Side Of Compound Assignment Is Saved Before Evaluation Of Right-Hand Side
class Test {
public static void main(String[] args) {
int k = 1;
int[] a = { 1 };
k += (k = 4) * (k + 2);
a[0] += (a[0] = 4) * (a[0] + 2);
System.out.println("k==" + k + " and a[0]==" + a[0]);
}
}
So the expression in the question is re-written and grouped as:
i = i ^ (j = j ^ (i = i ^ j));
Left-hand operands are evaluated:
i = 24 ^ (j = 17 ^ (i = 24 ^ 17));
**
Since the value of i is not "updated" as expected, it will cause the value of i to get 0 when 24 is swapped to j.
By writing your swap all in one statement, you are relying on side effects of the inner i ^= j expression relative to the outer i ^= (...) expression.
From the Java specificiation (15.26 Assignment Operators):
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.
[...]
AssignmentOperator: one of
= *= /= %= += -= <<= >>= >>>= &= ^= |=
You might want to consider the readability of the code. Perhaps it's best to e.g. put the code in a method called swap(), or do the actual swapping through the use of a temp variable:
int temp = i;
i = j;
j = temp;
The left-most i is being evaluated before it's changed.
You can instead do:
j ^= (i ^= j);
i ^= j;
Which is slightly less compact but works.
How about doing:
i ^= j ^ (j = j ^ i ^ j);
Here is a little shorter solution compared to #nhahtdh . I know it's an old question but just wanted to document it on Stackoverflow :P
i = i ^ j ^ (j = i)