Parenthesis, Comma Operator and Ternary operator combination equivalent in java - java

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;

Related

Java statements which are also expressions, please explain

Please help me interpret this sentence from a purely terminological point of view:
"Technically, because variable assignments can be used as values for further assignments or operations, they can be considered to be both statements and expressions."
What does technically mean? What is not technically?
In case of
a = (b = 1);
What we know:
a = (b = 1);
is statement.
(b = 1)
is an expression.
Question 1:
is
a = (b = 1);
also an expression?
Or it is only an expression when written like this
a = (b = 1)
without semi colon and used in another statement or expression?
Quesion 2:
Is
(b = 1)
also a statement (given it is an assignment)? Or every statement must end with ; ?
Question 3.
Is b an expression within
(b = 1)
Or it is just a variable?
Is 1 an expression within
(b = 1)
Or it is just a literal?
Is a an expression within
a = (b = 1)
Or it is just a variable?
Regardin Q3 some clarification:
I guess literals and variables can be expressions when they are on their own. For example in the statement:
a = 1;
1 is an expression.
But is it also true for 1 inside expression of the example statement:
a = (b = 1);
An expression is anything which can be evaluated to a value, so a = (b = 1) is an expression (it is an assignment expression where the right-hand operand is another assignment expression).
The code a = (b = 1); is a statement; note the semicolon ; at the end of it. Specifically, it is an expression statement. An expression statement is a statement formed by writing an expression followed by a semicolon. (Not every type of expression is allowed as an expression statement, for example 1 + 1; is not a valid statement.)
So strictly speaking, the semicolon makes the two pieces of code different. But if we are not being formal then we could say that a = (b = 1) can be written either as an expression or a statement.
To answer the rest of your questions about what is or isn't a statement or an expression, I suggest checking the Java Language Specification:
Chapter 14. Blocks and Statements
Chapter 15. Expressions

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.

EXP4J: can't get a good factorial operator working

I have the following factorial operator declared:
Operator factorial = new Operator("!", 1, true, Operator.PRECEDENCE_POWER + 1) {
#Override public double apply(double... args) {
final long arg = (long) args[0];
if ((double) arg != args[0]) {
throw new IllegalArgumentException("Operand for factorial has to be an integer");
}
if (arg < 0) {
throw new IllegalArgumentException("The operand of the factorial can not " +
"be " +
"less than zero");
}
double result = 1;
for (int i = 1; i <= arg; i++) {
result *= i;
}
return result;
}
};
So, it works fine when you have simple expressions such as 5! and so on, but things start to break when you try to emulate normal calculator behavior. The following example throws an IllegalArgumentException():
5!+5
Why? I guess it has something to do with 2 adjacent operators or something, since using (5!)+5 works with no issues.
This is devastating for the project I'm working on. Someone has suggested converting the operator into a function but that would take too much time. I've tried changing all the constructor parameters but none of them changed the problem.
I found a workaround that will make the factorial behave as intended. The trick is to add a second variable and make the factorial a pseudo unrary operator, so:
Instead of: 5!+5 I used: 5!(1)+5. This required no refactoring in my program, as the only change made was the way the operator was being inputted.
This way, the parser works wonderfully. You also need to change the actual Operator declaration to this:
Operator factorial = new Operator("!", 2, true, Operator.PRECEDENCE_POWER + 1) {
#Override public double apply(double... args) {
final long arg = (long) args[0];
if ((double) arg != args[0]) {
throw new IllegalArgumentException("Operand for factorial has to be an integer");
}
if (arg < 0) {
throw new IllegalArgumentException("The operand of the factorial can not " +
"be " +
"less than zero");
}
double result = 1;
for (int i = 1; i <= arg; i++) {
result *= i;
}
return result;
}
};
I suppose one should avoid using unary operators altogether when using EXP4J.
It certainly has to do with there being two operators in a row.
Or, alternatively, it has to do with EXP4J being a poor implementation of an expression parser.
Anyway you look at it, there is no simple solution using EXP4J. It is simply not up to the task of handling postfix operators. (If you were prepared to use !5 to mean "5 factorial", there wouldn't be a problem; just make sure that you give it the same precedence as the other unary prefix operators. But the fact that you don't want to use a function suggests that you don't want to change the syntax of ! either.)
The big hint is that the Operator constructor does not have any way to specify whether an operator is prefix or postfix. (! is a postfix operator, because it follows its operand, unlike, say, unary - with is prefix.)
If the expression parser doesn't know, it certainly cannot validate the input, and there's good reason to believe that it can't accurately parse it either. [Note 1] Another hint is that custom operators need to be declared as taking 1 or 2 operands, which means that a custom operator cannot act like - which has both prefix and infix syntax.
The special-case hack for unary + and - operators interacts badly with the hack which doesn't attempt to check whether a unary operator is prefix or postfix. In 5!+5, the + immediately follows an operator, which EXP4J interprets as indicating that the + is a prefix unary +. So it parses that almost as if it were (5!)(+5) except that it does not insert the implicit multiplication that it would insert if you actually wrote (5!)(+5).
So you get the exception, because you can't have two value side-by-side without an operator between them.
Actually fixing this would require quite a bit of rewriting. You might well be better off using a different expression evaluator, or throwing your own together with a standard parser generator.

One plus plus two compiles unexpectedly [duplicate]

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.

Java : large integer numbers error

I am trying to do the following math equation in Java:
(44334*(220*220))+ (81744*220) + 39416)
When I enter the same equation in WolframAlpha (or in Google) I get:
2163788696
In java I get negative number..
I have been struggling to find out why this is happening but with no luck.
I also tried saving the answer in a BigInteger, but then I get negative values because the digits are too large.
What should I do?
EDIT: To deal with the integer wrap-around, use a long:
System.out.println("Result: " +
(44334L * 220 * 220 + 81744 * 220 + 39416)); // 2163788696
The plus operator is left-associative (whether it's being used for string concatenation or addition), so if the entire arithmetic expression weren't parenthesized, it would be concatenating the results of the sub-expressions as individual strings from left to right.
The left operand determines whether + is used for string concatenation or addition. In this case, the first operand is a string, so the right side ((44334*(220*220))) is converted into a string as well. The result of the first + operator is a string and is used as the left side of another + string concatenation operation. the next operand ((81744*220)) gets converted to a string again.
You can put parentheses around the entire arithmetic expression to avoid that.
Right now, what you are doing is equivalent to:
System.out.println(("result="+(44334*220*220)) + (81744*220 + 39416) );
// = "result=2145765600" + 18023096
// = "result=214576560018023096"
Parentheses are important! Here is your code fixed:
System.out.println("result=" + (44334*220*220+ 81744*220 + 39416) );
// = "result=2163788696"
EDIT:
Also beware of automatic int casting. Use longs because your result is bigger than MAX_INT (but smaller than MAX_LONG which is 9223372036854775807).
(long)((long)44334*220*220 + (long)81744*220 + 39416)
Or put the suffix L after your numbers (so they're considered as longs).
The problem is due to the fact that the expression is evaluated from left to right. The first value is of type string, so the + operator then becomes the string concatenation operator instead of the mathmatical addition operator. The expressions (44334*(220*220)) and (81744*220) are then evaluated and converted to strings leading to an incorrect result. If you surround the entire expression with parentheses, the result is calculated properly and you see the correct result.
For the BigInteger version, try this, it will work correctly
BigInteger a = new BigInteger("44334").multiply(new BigInteger("220").multiply(new BigInteger("220")));
BigInteger b = new BigInteger("81744").multiply(new BigInteger("220"));
BigInteger c = new BigInteger("39416");
c = c.add(a).add(b);
System.out.println("resultVersA="+(44334*(220*220))+ (81744*220) + 39416 );
System.out.println("resultVersB="+ c);
The result will be:
resultVersA=21457656001798368039416
resultVersB=2163788696
The problem is that the + operator in Java is overloaded. It can mean either string concatenation or numeric addition. What is going on is that some of the + operations are being treated as string concatenations rather that numerical additions.
You need to either add a set of parentheses around the expression,
System.out.println("result="+((44334*(220*220))+ (81744*220) + 39416));
or use a temporary variable.
int res = (44334*(220*220))+ (81744*220) + 39416;
System.out.println("result="+res);
"The rules" that Java uses to determine the meaning of + are roughly as follows:
If the type of the left OR right operand is String, then the + means string concatenation.
If the types of both the left AND right operands are primitive numeric types or numeric wrapper types, then the + means a numeric addition.
Otherwise this is a compilation error.
The other problem here is that 2163788696 is greater than the largest int value - 2147483647. So to get the right answer (without overflow), you need to tell Java to use long arithmetic; e.g.
System.out.println("result=" + ((44334L * (220 * 220)) + (81744 * 220) + 39416));
If you don't then result will be a negative number ... in this example.
You could also use BigInteger, but it is a bit cumbersome, and long will do just fine here.
Just put an L after every number you write.
(44334L*(220L*220L))+ (81744L*220L) + 39416L

Categories

Resources