(Note: I came across this somewhat accidentally, so it may not be practical, but I am just very curious)
I wanted to print out a value, which was the sum of two values, after incrementing the second. Something like so:
int first = 10;
int second = 20;
System.out.println(first + ++second); //31
System.out.println(first); //10
System.out.println(second); //21
Maybe not the neatest code, but it worked. But then, I started experimenting.
System.out.println(first +++ second); //30
System.out.println(first); //11
System.out.println(second); //21
That's fine; it means that the first was incremented after being added, and that whitespace can be ignored here. Cool. But then...
System.out.println(first +++++ second); //"Invalid Argument", doesn't work
While
System.out.println(first ++ + ++ second); //31
System.out.println(first); //11
System.out.println(second); //21
Works fine, but for some reason, is still different than
System.out.println(first + + + ++ second); //31
System.out.println(first); //10
System.out.println(second); //21
And maybe the strangest of all,
System.out.println(first + + + + + + second); //30
System.out.println(first); //10
System.out.println(second); //20
So what's going on here? When is whitespace between operators ignored, and when is it not? Why can I write "+ + + + +", without any issues?
Thanks!
This comes down to operator precedence. The order of operations goes:
postfix (foo++, foo--)
unary (++foo, --foo, +expr, ...)
...
additive (+, -)
...
So, let's take a look at each expression:
first + ++second is first + (++second). That's fine.
first +++ second is (first++) + second, which works as you said it does.
first +++++ second is ((first ++)++)+ second), but (first ++) is a value (not a variable) and thus can't be incremented -- that's what the error is trying to tell you.
first ++ + ++ second explicitly tells Java to split things up differently than above: it becomes (first ++) + (++ second), which is fine.
first + + + + + + second becomes first + (+ (+ (+ (+ (+ second))))). The unary + just means "not negated", so +foo == foo. Therefore this expression simplifies to first + second, which is obviously fine.
I don't want to close it as a duplicate since it's a different language but I believe it to be the same reason as layed out here.
It's simply a matter of parsing and these bullets should help you figure it out:
Java allows for a lot of whitespace
Consecutive mathematical operators like + bear no extra meaning and only one will be applied
Parsing is done from left to right
Code: first +++ second
Parsed: first++ + second
Code: first +++++ second
Parsed: There is no binary operator ++ since it will try to make ++ ++ +
Code: first ++ + ++ second
Parsed: first++ + ++second
Code: first + + + ++ second
Parsed: first + ++second
Code: first + + + + + + second
Parsed: first + second
I think the parser is greedy, i.e. it always eats as many plus-signs as available, for reducing them to the increment operator if possible.
I.e. it goes from left to right and when it spots two subsequent plus-signs, it evaluates them as increment operator, while a single plus sign followed by a non-plus-symbol is evaulated as a binary plus or as unary plus, depending on the left side operand.
Related
Can any one explain what below statement is doing ? Actually I want to translate code shown here in java, so its real code
w = (m<3?y--,m+=13:m++,d+153*m/5+15*y+y/4+19*c+c/4+5);
I searched a lot but not able to found what this statement is doing. Can anyone explain it and help me to convert it into Java code ? I never seen combination of Unary Operators in Ternary Operators in C language. Sorry for simple question if it is but I did not understand it.
This:
w = (m<3?y--,m+=13:m++,d+153*m/5+15*y+y/4+19*c+c/4+5);
Works out to be the same as this:
if (m<3) {
y--;
m+=13;
} else {
m++;
}
w = (d + (153*m/5) +(15*y) + (y/4) + (19*c) + (c/4) + 5);
Now for the explanation. There is an instance of the ternary operator here. The second clause is an expression which allows for the comma operator, while the third clause is a conditional expression meaning it can't include the comma operator (not without surrounding parenthesis, at least). This means that the first comma you see is part of the second clause while the second comma marks the end of the conditional.
So the expression with implicit parenthesis would look like this:
w = (((m<3)?(y--,m+=13):m++), (d + (153*m/5) +(15*y) + (y/4) + (19*c) + (c/4) + 5));
And the part that makes up the conditional is:
(m<3)?(y--,m+=13):m++
And because this is the left operand of the comma operator, the result of the expression isn't used so it can be pulled out of the larger expression:
(m<3)?(y--,m+=13):m++
w = (d + (153*m/5) +(15*y) + (y/4) + (19*c) + (c/4) + 5);
And the conditional can then be further translated into an if/else block as above.
I'll try.
m<3?
Is essentially
if (m < 3)
If it evaluates as true, y is decremented and 13 is added to m.
If it evaluates as false, m is incremented and then I think that w is set to whatever the result of "d+153m/5+15y+y/4+19*c+c/4+5" is.
You can de-obfuscate it quite a bit by dropping the conditional and comma operators:
if(m<3)
{
y--;
m+=13;
}
else
{
m++;
}
w = d + 153*m/5 + 15*y + y/4 + 19*c + c/4 + 5;
I am trying to understand how the compiler views the following print statements. It is simple yet a bit intriguing.
This prints the added value. Convincing enough.
System.out.println(1+2); //output: 3
The output from the following looks convincing as well:
System.out.println(1+2+"3");//output: 33
My question (based on the behavior above) is here.
System.out.println("1"+2+3);//Should be 15 right? NO. It is 123.
I tried few other such statements which were along the same lines. I was able to see one two clear behaviors.
If integers are at the front, without the quotes, they are added and subsequent integers are just appended as suffix to the added values from the front.
if the statement starts with string, under quotes, then all other subsequent elements get appended as suffix.
Is this somewhere in the java api docs? Or just very obvious string or add operator behavior which I am not seeing. Any of your valuable insights will be appreciated.
Here is the code snippet:
public static void main(String[] args) {
System.out.println(1+2);
System.out.println(1+2+"3");
System.out.println("1"+2+3);
System.out.println("1"+2+"3");
System.out.println("1"+2);
}
// The Console output:
// 3
// 33
// 123
// 123
// 12
I guess the Java specification explains it best:
The + operator is syntactically left-associative, no matter whether it
is determined by type analysis to represent string concatenation or
numeric addition. In some cases care is required to get the desired
result. For example, the expression:
a + b + c
is always regarded as meaning:
(a + b) + c
So, if a was a String, then it concatenates with b. The result would be of String type, hence it continues to concatenate with c.
I also found this interesting. I haven't worked too much in java recently but I found out a little bit of info that might be helpful through playing with it.
I think this has to do with automatic Type-casting that java does.
System.out.println("1"+2+3);
Prints 123 as you said. Since "1" is casted as string, Java assumes since the first one was a string, the ones following will be a string for concatenation unless otherwise noted
Although, this result does print 15 when you define the type
System.out.println("1" + (int)(2+3));
In that case, it can complete the operation before concatenating.
So I think java is assuming if the first one is a String, that the rest are going to be strings and to concatenate them.
EDIT: you can see some info about automatic type-conversion on oracle's website here
The + operator is overloaded in the compiler. If both operands are numeric, + is addition. If either or both operands are String, + is string concatenation. (If one operand is String and the other is numeric, the number is cast to a String). Finally, + binds left-to-right.
All this causes a compound formula a + b + c + ... to do addition left-to-right until it hits the first string operand, at which point it switches to string concatenation for the remainder of the formula. So...
"1" + 2 + 3 + 4 = 1234 /* cat cat cat */
1 + "2" + 3 + 4 = 1234 /* cat cat cat */
1 + 2 + "3" + 4 = 334 /* add cat cat */
1 + 2 + 3 + "4" = 64 /* add add cat */
Thats interesting part of string.
When a String is added to any other data type, the resultant value is a String.The other variable is also converted to a String and then concatenated. However, when two integers are operated with a + sign, the + acts as an addition operator and not a concatenation operator.
If the expression within the println() or print() method contains parentheses, then the value within the parentheses is evaluated first. Consider the following example:
int a = 5;
int b = 6;
System.out.println(a + b); // Output will be: 11
System.out.println("5" + "6"); // Output will be: 56
System.out.println("" + a + b); // Output will be: 56
System.out.println(5 + 6 + a + " " + b + a); // Output will be: 16 65
System.out.println("Result: " + a + b); // Output will be: 56
System.out.println("Result: " + (a + b)); // Output will be: 11
You can see the difference between last two sysout statements
I am trying to understand how the compiler views the following print statements. It is simple yet a bit intriguing.
This prints the added value. Convincing enough.
System.out.println(1+2); //output: 3
The output from the following looks convincing as well:
System.out.println(1+2+"3");//output: 33
My question (based on the behavior above) is here.
System.out.println("1"+2+3);//Should be 15 right? NO. It is 123.
I tried few other such statements which were along the same lines. I was able to see one two clear behaviors.
If integers are at the front, without the quotes, they are added and subsequent integers are just appended as suffix to the added values from the front.
if the statement starts with string, under quotes, then all other subsequent elements get appended as suffix.
Is this somewhere in the java api docs? Or just very obvious string or add operator behavior which I am not seeing. Any of your valuable insights will be appreciated.
Here is the code snippet:
public static void main(String[] args) {
System.out.println(1+2);
System.out.println(1+2+"3");
System.out.println("1"+2+3);
System.out.println("1"+2+"3");
System.out.println("1"+2);
}
// The Console output:
// 3
// 33
// 123
// 123
// 12
I guess the Java specification explains it best:
The + operator is syntactically left-associative, no matter whether it
is determined by type analysis to represent string concatenation or
numeric addition. In some cases care is required to get the desired
result. For example, the expression:
a + b + c
is always regarded as meaning:
(a + b) + c
So, if a was a String, then it concatenates with b. The result would be of String type, hence it continues to concatenate with c.
I also found this interesting. I haven't worked too much in java recently but I found out a little bit of info that might be helpful through playing with it.
I think this has to do with automatic Type-casting that java does.
System.out.println("1"+2+3);
Prints 123 as you said. Since "1" is casted as string, Java assumes since the first one was a string, the ones following will be a string for concatenation unless otherwise noted
Although, this result does print 15 when you define the type
System.out.println("1" + (int)(2+3));
In that case, it can complete the operation before concatenating.
So I think java is assuming if the first one is a String, that the rest are going to be strings and to concatenate them.
EDIT: you can see some info about automatic type-conversion on oracle's website here
The + operator is overloaded in the compiler. If both operands are numeric, + is addition. If either or both operands are String, + is string concatenation. (If one operand is String and the other is numeric, the number is cast to a String). Finally, + binds left-to-right.
All this causes a compound formula a + b + c + ... to do addition left-to-right until it hits the first string operand, at which point it switches to string concatenation for the remainder of the formula. So...
"1" + 2 + 3 + 4 = 1234 /* cat cat cat */
1 + "2" + 3 + 4 = 1234 /* cat cat cat */
1 + 2 + "3" + 4 = 334 /* add cat cat */
1 + 2 + 3 + "4" = 64 /* add add cat */
Thats interesting part of string.
When a String is added to any other data type, the resultant value is a String.The other variable is also converted to a String and then concatenated. However, when two integers are operated with a + sign, the + acts as an addition operator and not a concatenation operator.
If the expression within the println() or print() method contains parentheses, then the value within the parentheses is evaluated first. Consider the following example:
int a = 5;
int b = 6;
System.out.println(a + b); // Output will be: 11
System.out.println("5" + "6"); // Output will be: 56
System.out.println("" + a + b); // Output will be: 56
System.out.println(5 + 6 + a + " " + b + a); // Output will be: 16 65
System.out.println("Result: " + a + b); // Output will be: 56
System.out.println("Result: " + (a + b)); // Output will be: 11
You can see the difference between last two sysout statements
This question already has answers here:
Why does this Java code with "+ +" compile?
(8 answers)
Closed 8 years ago.
So, I expect this not to compile, and it doesn't:
// the two is inc'd, so reduces symbolically to println(int int)
// which is a compile error
System.out.println(1 ++ 2);
But this does:
System.out.println(1 + + 2); // returns three
What gives? Shouldn't it also not compile?
Also, this question is very hard to search for because of the operators..
Java is interpreting the working 1 + + 2 as 1 plus positive 2. See the Unary operator section.
From the Specification, on Lexical Translations
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. There is one exception: if lexical
translation occurs in a type context (§4.11) and the input stream has
two or more consecutive > characters that are followed by a non->
character, then each > character must be translated to the token for
the numerical comparison operator >.
(Also known as maximal munch.)
The ++ is interpreted as a postfix increment operator which cannot be applied to an integer literal, thus the compiler error.
While
1 + + 2
each character is interpreted separately. 1 is an integer literal, + is the additive operator, + is the unary plus operator, and 2 is an integer literal. The whole expression is equivalent to
1 + (+2)
which is easier to read.
In Java/C++/C ++ is not same as + +. ++/-- are the Increment/Decrement operator.
The first case does not work because it does not apply to literals (1 or 2).
Even then it would not be a valid statement, Neither 1++ 2 nor 1 ++2 are valid statement in Java. The second example works because it is interpreted as 1 + (+2). The Java lexer ignores white space. In the same way this is valid :
1 + + + 2 --> 1 + (+ (+2))
Or
1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 2
It works only because + is a unary operator. It does not work for strings as below :
"a" + + "b" // does not work because +"b" is not valid.
Similarly it is not valid with multiplication
1 * * 2 // does not work because *2 is not valid.
Sometimes it's easier to see a problem using variables.
Your snippet could be rewritten as:
int a = 1;
int b = +2;
System.out.println(a + b);
Now, you can easily see that the second + operator is used to indicate a positive value.
You could also have written +1 + +2.
The - operator could be used to negate an expression.
+ and - are unary operators.
The message is:
Main.java:14: error: ')' expected
System.out.println(1 ++ 2);
^
The 1 ++ 2 statement is parsed as 1 followed by ++ followed by 2. This is interpreted as 1++ and 2 creating a syntax error (and not an unexpected type error; in fact, you will get the same error if you used variables e.g. i ++ j).
The 1 + + 2 statement on the other hand is parsed as 1 followed by + followed by +2 which compiles as expected. The space between the two operators separates the two operators.
last exam we had the exercise to determine the output of the following code:
System.out.println(2 + 3 + ">=" + 1 + 1);
My answer was 5 >= 2 but now I realize that this is the wrong answer. It should be 5 >= 11.
But why?
Assuming that your syntax is :
System.out.println(2 + 3 + ">=" + 1 + 1);
expressions are evaluated from left to right, in this case 2 + 3 get summed to 5 and when "added" to a string result in "5 >=", which when added to 1 gives "5 >= 1", add another 1 and your result is: "5 >= 11"
Because "adding" a string to anything results in concatenation. Here is how it gets evaluated in the compilation phase:
((((2 + 3) + ">=") + 1) + 1)
The compiler will do constant folding, so the compiler can actually reduce the expression one piece at a time, and substitute in a constant expression. However, even if it did not do this, the runtime path would be effectively the same. So here you go:
((((2 + 3) + ">=") + 1) + 1) // original
(((5 + ">=") + 1) + 1) // step 1: addition (int + int)
(("5>=" + 1) + 1) // step 2: concatenation (int + String)
("5>=1" + 1) // step 3: concatenation (String + int)
"5>=11" // step 4: concatenation (String + int)
You can force integer addition by sectioning off the second numeric addition expression with parentheses. For example:
System.out.println(2 + 3 + ">=" + 1 + 1); // "5>=11"
System.out.println(2 + 3 + ">=" + (1 + 1)); // "5>=2"
Number+number=number
number+string=string
string+number=string
etc.
It is evaluated from left to right. You concatenate"1" to "5 >=" and finally "1" to "5 >= 1".
Let's read it one token at a time from left to right:
The first literal encountered is an integer, 2, then a +, then another integer, 3. A + between two integers is addition, so they are added together to be 5.
Now we have 5, an integer, then a +, then a String ">=". A + between an integer and a String is a concatenation operator. So the Strings are combined to form "5>=".
Then we have "5>=", a String, a +, and then an integer, 1. This is String concatenation again. So the result is "5>=1".
Finally we have "5>=1", a String, a +, and the a 1. his is String concatenation again. So the result is "5>=11".