Why are assignment chains are evaluated in right to left order?
i = j = k = 10;
is
k = 10;
j = k;
i = j;
Addition is evaluated left to right:
public static void main(String[] args)
{
int i = m1() + m2() + m3();
}
public static int m1()
{
System.out.println("m1");
return 1;
}
public static int m2()
{
System.out.println("m2");
return 2;
}
public static int m3()
{
System.out.println("m3");
return 3;
}
Output:
m1
m2
m3
According to which rule are assignment operator chains processed in right to left order?
Why? Because that's the most useful order, and seems to conform to most people's expectations, perhaps in part because that's the usual case.
The other way round would be surprising (i.e., a source of bugs):
int k;
j = 42;
i = j = k = 10;
Left to right leaves i at 42, j undefined, and k 10. Right to left makes all 3 variables have the value 10, much more useful.
Which rule? https://docs.oracle.com/javase/specs/jls/se10/html/jls-15.html#jls-15.26
Chainable assignment is right-associative (i.e. right to left) simply because that is the only way it would make sense. The operation i = j = k = 10 is supposed to assign 10 to all three variables. If it was done left to right, it would evaluate to
i = j;
j = k;
k = 10;
Rather, than assigning the same value to all three, it would be "shifting" the values: i gets the old value of j, j gets the old value of k, and only k gets the value 10. Now, this could possibly be a useful operation to have, but it is not the intended behaviour here, so it has to be done from right to left.
Also, going left to right would evaluate to ((i = j) = k) = 10, which would be putting an rvalue (the assignment expression as a whole is an rvalue) on the left side of an assignment, which is not allowed.
The evaluation order is specified in the Java Language Specification (JLS). In section 15.26 Assignment Operators is written
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.
This means, that the right-most assignment is performed first, then then next to the left etc.
Generally, the precedence of operations is specified by the grammar of Java. This also specifies why additions are performed after multiplications.
Concerning you first question: It would be quite counter-intuitive to evaluate the assignment in a different order, as the variables could have different values afterwards.
Related
In the method normalize I input an array say, {1, 2, 3, 4}, and the return is a normalized array, {0.1, 0.2, 0.3, 0.4}.
I know I should introduce a new array in the method (b in the following), but why actually?
public static double[] normalize(double[] a) {
double[] b = new double[a.length];
double sum = 0;
for (int i = 0; i < b.length; i++) {
sum += a[i];
}
for (int i = 0; i < b.length; i++) {
b[i] = a[i]/sum;
}
return b;
}
Input: 1 2 3 4
Output: 0.1 0.2 0.3 0.4
Why is the following wrong:
public static double[] normalize(double[] a) {
double sum = 0;
for (int i = 0; i < a.length; i++) {
sum += a[i];
}
for (int i = 0; i < a.length; i++) {
a[i] = a[i]/sum;
}
return a;
}
Input: 1 2 3 4
Output: 0.1 0.2 0.3 0.4
The difference is that one method updates the input array in place, whereas the other one keeps the array intact and returns a copy.
Neither is wrong(*), both ways have their place, you just need to make sure to the caller knows what is happening.
If you update in-place, you can make that clearer by making the method void instead of returning a (redundant) reference to the same array.
(*) In modern practice, prefer immutable data structures. So unless performance is a real issue, go with the "safer" variant.
In the first case, the original array will stay unmodified when the method returns.
In the second case, the original array will be modified (even when it returns to where it was called), irregardless to whatever array you set the return value to afterward.
Both options can be viable, but it depends on the case and what is expected to happen. However, typically I would expect when you pass a parameter to a method, the parameter will not be modified when the method returns.
Documentation can make it clear that the original array will be modified or if it will not be.
Side Note:
This will not work the same way if you modify a directly, instead of modifying the values contained within:
public static void normalize(double[] a) {
a = new double[5];
}
a will remain unchanged in this case when the method returns.
In my opinion, you are creating a new variable with new values. The method receives one var and returns another var.
It's more reader-friendly.
Explaining the byte code behavior, and the difference of creating a new array or reusing the same input is not what you are asking for I think. Because it is really easy to see the difference.
What I think you are looking for, is a conceptual analysis of the difference. From my perspective, "functions" in any language should be treated as math functions. You give X and Y, and the function returns Z. Imagine you have a rectangle which height = a and width = b. If you want the area of it, you pass a and b and you get A . If you want the perimeter, you pass a and b and you get P.
This makes your code more readable, reusable, more cohesive, more testable.
I was going through some exercises but I am confused in this one:
public static int f (int x, int y) {
int b=y--;
while (b>0) {
if (x%2!=0) {
--x;
y=y-2;
}
else {
x=x/2;
b=b-x-1;
}
}
return x+y;
}
What is the purpose of b=y--?
So, for example, x=5 and y=5
when we first go inside of while loop (while (b>0)) will b = 4 or 5? When I am running the code in my computer b is 5. And the return is 3. It is really unclear to me. Sorry if I am unclear in my question.
int b=y--; first assignes b=y and then decrements y (y--).
Also take a look at the prefix/postfix unary increment operator.
This example (taken from the linked page) demonstrates it:
class PrePostDemo {
public static void main(String[] args){
int i = 3;
i++;
// prints 4
System.out.println(i);
++i;
// prints 5
System.out.println(i);
// prints 6
System.out.println(++i);
// prints 6
System.out.println(i++);
// prints 7
System.out.println(i);
}
}
The difference between a post-increment/decrement and a pre-increment/decrement is in the evaluation of the expression.
The pre-increment and pre-decrement operators increment (or decrement) their operand by 1, and the value of the expression is the resulting incremented (or decremented) value. In contrast, the post-increment and post-decrement operators increase (or decrease) the value of their operand by 1, but the value of the expression is the operand's original value prior to the increment (or decrement) operation.
In other words:
int a = 5;
int b;
b = --a; // the value of the expression --a is a-1. b is now 4, as is a.
b = a--; // the value of the expression a-- is a. b is still 4, but a is 3.
Remember that a program must evaluate expressions to do everything. Everything is an expression, even just a casual mention of a variable. All of the following are expressions:
a
a-1
--a && ++a
System.out.println(a)
Of course, in the evaluation of expressions, operator precedence dictates the value of an expression just as the PEMDAS you learned in grade school. Some operators, such as increment/decrement, have side effects, which is of course great fun, and one of the reasons why functional programming was created.
I believe b would equal 5 entering the loop because
b=y--;
When the "--" is behind the variable it decrements it after the action.
It's poor coding, as it can confuse new programmers.
The function, assuming it is passing by value, like in the example above (as opposed to passing by reference) takes a copy of y, decrements it, and assigns it to b. It does not alter the argument passed to the function when it was called.
Post increment
x++;
x += 1;
Post decrement
x--;
x -=1;
Pre increment : ++x;
Pre decrement : --x;
According to the Head First Java:
Difference between x++ and ++x :
int x = 0; int z = ++x;
Produces: x is 1, x is 1
in x = 0; int z = x++;
Produces: x is 1, z is 0
I have an array of operations and a target number.
The operations could be
+ 3
- 3
* 4
/ 2
I want to find out how close I can get to the target number by using those operations.
I start from 0 and I need to iterate through the operations in that order, and I can choose to either use the operation or not use it.
So if the target number is 13, I can use + 3 and * 4 to get 12 which is the closest I can get to the target number 13.
I guess I need to compute all possible combinations (I guess the number of calculations is thus 2^n where n is the number of operations).
I have tried to do this in java with
import java.util.*;
public class Instruction {
public static void main(String[] args) {
// create scanner
Scanner sc = new Scanner(System.in);
// number of instructions
int N = sc.nextInt();
// target number
int K = sc.nextInt();
//
String[] instructions = new String[N];
// N instructions follow
for (int i=0; i<N; i++) {
//
instructions[i] = sc.nextLine();
}
//
System.out.println(search(instructions, 0, N, 0, K, 0, K));
}
public static int search(String[] instructions, int index, int length, int progressSoFar, int targetNumber, int bestTarget, int bestDistance) {
//
for (int i=index; i<length; i++) {
// get operator
char operator = instructions[i].charAt(0);
// get number
int number = Integer.parseInt(instructions[i].split("\\s+")[1]);
//
if (operator == '+') {
progressSoFar += number;
} else if (operator == '*') {
progressSoFar *= number;
} else if (operator == '-') {
progressSoFar -= number;
} else if (operator == '/') {
progressSoFar /= number;
}
//
int distance = Math.abs(targetNumber - progressSoFar);
// if the absolute distance between progress so far
// and the target number is less than what we have
// previously accomplished, we update best distance
if (distance < bestDistance) {
bestTarget = progressSoFar;
bestDistance = distance;
}
//
if (true) {
return bestTarget;
} else {
return search(instructions, index + 1, length, progressSoFar, targetNumber, bestTarget, bestDistance);
}
}
}
}
It doesn't work yet, but I guess I'm a little closer to solving my problem. I just don't know how to end my recursion.
But maybe I don't use recursion, but should instead just list all combinations. I just don't know how to do this.
If I, for instance, have 3 operations and I want to compute all combinations, I get the 2^3 combinations
111
110
101
011
000
001
010
100
where 1 indicates that the operation is used and 0 indicates that it is not used.
It should be rather simple to do this and then choose which combination gave the best result (the number closest to the target number), but I don't know how to do this in java.
In pseudocode, you could try brute-force back-tracking, as in:
// ops: list of ops that have not yet been tried out
// target: goal result
// currentOps: list of ops used so far
// best: reference to the best result achieved so far (can be altered; use
// an int[1], for example)
// opsForBest: list of ops used to achieve best result so far
test(ops, target, currentOps, best, opsForBest)
if ops is now empty,
current = evaluate(currentOps)
if current is closer to target than best,
best = current
opsForBest = a copy of currentOps
otherwise,
// try including next op
with the next operator in ops,
test(opsAfterNext, target,
currentOps concatenated with next, best, opsForBest)
// try *not* including next op
test(opsAfterNext, target, currentOps, best, opsForBest)
This is guaranteed to find the best answer. However, it will repeat many operations once and again. You can save some time by avoiding repeat calculations, which can be achieved using a cache of "how does this subexpression evaluate". When you include the cache, you enter the realm of "dynamic programming" (= reusing earlier results in later computation).
Edit: adding a more OO-ish variant
Variant returning the best result, and avoiding the use of that best[] array-of-one. Requires the use of an auxiliary class Answer with fields ops and result.
// ops: list of ops that have not yet been tried out
// target: goal result
// currentOps: list of ops used so far
Answer test(ops, target, currentOps, opsForBest)
if ops is now empty,
return new Answer(currentOps, evaluate(currentOps))
otherwise,
// try including next op
with the next operator in ops,
Answer withOp = test(opsAfterNext, target,
currentOps concatenated with next, best, opsForBest)
// try *not* including next op
Answer withoutOp = test(opsAfterNext, target,
currentOps, best, opsForBest)
if withOp.result closer to target than withoutOp.target,
return withOp
else
return withoutOp
Dynamic programming
If the target value is t, and there are n operations in the list, and the largest absolute value you can create by combining some subsequence of them is k, and the absolute value of the product of all values that appear as an operand of a division operation is d, then there's a simple O(dkn)-time and -space dynamic programming algorithm that determines whether it's possible to compute the value i using some subset of the first j operations and stores this answer (a single bit) in dp[i][j]:
dp[i][j] = dp[i][j-1] || dp[invOp(i, j)][j-1]
where invOp(i, j) computes the inverse of the jth operation on the value i. Note that if the jth operation is a multiplication by, say, x, and i is not divisible by x, then the operation is considered to have no inverse, and the term dp[invOp(i, j)][j-1] is deemed to evaluate to false. All other operations have unique inverses.
To avoid loss-of-precision problems with floating point code, first multiply the original target value t, as well as all operands to addition and subtraction operations, by d. This ensures that any division operation / x we encounter will only ever be applied to a value that is known to be divisible by x. We will essentially be working throughout with integer multiples of 1/d.
Because some operations (namely subtractions and divisions) require solving subproblems for higher target values, we cannot in general calculate dp[i][j] in a bottom-up way. Instead we can use memoisation of the top-down recursion, starting at the (scaled) target value t*d and working outwards in steps of 1 in each direction.
C++ implementation
I've implemented this in C++ at https://ideone.com/hU1Rpq. The "interesting" part is canReach(i, j); the functions preceding this are just plumbing to handle the memoisation table. Specify the inputs on stdin with the target value first, then a space-separated list of operations in which operators immediately preceed their operand values, e.g.
10 +8 +11 /2
or
10 +4000 +5500 /1000
The second example, which should give the same answer (9.5) as the first, seems to be around the ideone (and my) memory limits, although this could be extended somewhat by using long long int instead of int and a 2-bit table for _m[][][] instead of wasting a full byte on each entry.
Exponential worst-case time and space complexity
Note that in general, dk or even just k by itself could be exponential in the size of the input: e.g. if there is an addition, followed by n-1 multiplication operations, each of which involves a number larger than 1. It's not too difficult to compute k exactly via a different DP that simply looks for the largest and smallest numbers reachable using the first i operations for all 1 <= i <= n, but all we really need is an upper bound, and it's easy enough to get a (somewhat loose) one: simply discard the signs of all multiplication operands, convert all - operations to + operations, and then perform all multiplication and addition operations (i.e., ignoring divisions).
There are other optimisations that could be applied, for example dividing through by any common factor.
Here's a Java 8 example, using memoization. I wonder if annealing can be applied...
public class Tester {
public static interface Operation {
public int doOperation(int cur);
}
static Operation ops[] = { // lambdas for the opertions
(x -> x + 3),
(x -> x - 3),
(x -> x * 4),
(x -> x / 2),
};
private static int getTarget(){
return 2;
}
public static void main (String args[]){
int map[];
int val = 0;
int MAX_BITMASK = (1 << ops.length) - 1;//means ops.length < 31 [int overflow]
map = new int[MAX_BITMASK];
map[0] = val;
final int target = getTarget();// To get rid of dead code warning
int closest = val, delta = target < 0? -target: target;
int bestSeq = 0;
if (0 == target) {
System.out.println("Winning sequence: Do nothing");
}
int lastBitMask = 0, opIndex = 0;
int i = 0;
for (i = 1; i < MAX_BITMASK; i++){// brute force algo
val = map[i & lastBitMask]; // get prev memoized value
val = ops[opIndex].doOperation(val); // compute
map[i] = val; //add new memo
//the rest just logic to find the closest
// except the last part
int d = val - target;
d = d < 0? -d: d;
if (d < delta) {
bestSeq = i;
closest = val;
delta = d;
}
if (val == target){ // no point to continue
break;
}
//advance memo mask 0b001 to 0b011 to 0b111, etc.
// as well as the computing operation.
if ((i & (i + 1)) == 0){ // check for 2^n -1
lastBitMask = (lastBitMask << 1) + 1;
opIndex++;
}
}
System.out.println("Winning sequence: " + bestSeq);
System.out.println("Closest to \'" + target + "\' is: " + closest);
}
}
Worth noting, the "winning sequence" is the bit representation (displayed as decimal) of what was used and what wasn't, as the OP has done in the question.
For Those of you coming from Java 7, this is what I was referencing for lambdas: Lambda Expressionsin GUI Applications. So if you're constrained to 7, you can still make this work quite easily.
I want to solve the following problem: You are given an n x n 2D matrix representing an image.
Rotate the image by 90 degrees (clockwise) in-place. I found one very nice solution here: http://n00tc0d3r.blogspot.de/2013/05/rotate-image.html Namely,
public void rotate(int[][] matrix) {
for (int level = 0, len = matrix.length; level < len; ++level, --len) {
int end = len - 1;
for (int pos = level; pos < end; ++pos) {
int tail = matrix.length - pos - 1;
int tmp = matrix[level][pos];
// left -> top
matrix[level][pos] = matrix[tail][level];
// bottom -> left
matrix[tail][level] = matrix[end][tail];
// right -> bottom
matrix[end][tail] = matrix[pos][end];
// top -> right
matrix[pos][end] = tmp;
}
}
}
I see that it works, and I understand the idea, but my question is why we use ++level instead of level++ and why we use --len instead of len--. I tried both was and it worked fine for me. However for such problems (non trivial matrix traversal) people always use ++level instead of level++. Again my question is why?
Consider this :
i = 0;
System.out.println(i++); // postfix increment
This prints 0, but i is updated to 1 as you expect.
i = 0;
System.out.println(++i); // prefix increment
This prints 1.
From Java Langauge Specification,
The value of the postfix increment expression is the value of the variable before the new value is stored.
And
The value of the prefix increment expression is the value of the variable after the new value is stored.
In your case of a for loop, it does not make a difference on which one you use, but it's really a matter of choice and habit.
There is no difference between using ++level or level++ / --len or len-- in an increment/decrement part of the for loop. The len or level values are not used in that section of the loop. so, the values are going to be very same after the execution of that part of the for loop. It is just programmer's decision. That's all
++level is evaluated after the increment and level++ before. The difference is subtle.
As the values of ++level and ++len aren't used in any expressions it's just a matter of style.
It does not have any effect in this "for" loop, but the prefix operator is applied before evaluation of the expression it is used within and the suffix operator after evaluation.
An example where it would make a difference is
while (i++ < 5)
{
foo(bar);
}
or
while (++i < 5)
{
foo(bar);
}
(The former one will go through one additional iteration compared to the latter one since it increments after evaluation of the comparison)
say I have a piece of code in a local method
int a = 5, b;
and then some code to indirectly initialize B such as
if (true) b = 5; // legal
if (someBool) b = 10; else b = 7; // legal
if (false) b = 5; // illegal
illegal even though B will always be initialized
if (a > 10)
b = 4;
if (a <= 10)
b = 4;
My question is what are all of the exact circumstances in which a local variable can be legitimately considered "initialized"?
A local variable can be considered to be "initialized" if the compiler can easily deduce that every possible code path will lead through a path where the value has been set.
if(true) can be determined to always run.
if(false) can be determined to never run.
if/else can be determined to run at least one of the branches, so you must assign the variable in each branch if you want it to be guaranteed initialized. Same principle applies for if/else if/.../else
switch statements will either run one of the possible cases, or will hit the default case, so if you assign the variable in all of these places then it can be guaranteed initialized.
The Java compiler doesn't bother checking all the possible values of each variable at various points in the method when making this determination, because variables are variable--they can change. However, if values can be considered constant then it can safely assume they won't change.
For example, the compiler doesn't care if you assign a variable and never change it in your code:
boolean val = true;
if(val) {
b = 5;
}
Debuggers and things make it possible for you to change the value of val on-the-fly, so the compiler doesn't make any assumptions here. However, if you make val constant, by declaring it final and initializing it with a constant or literal value, then the compiler will treat it exactly the same as if you'd used the constant value in code.
final boolean val = true;
if(val) { // Same as if you'd said `if(true)`
b = 5;
}
Such constants can be chained, as well, and the compiler will simplify them to their constant values rather than maintaining the longer expressions and operators:
final int five = 5;
final int four = five - 1; // Same as `four = 5 - 1`, or `four = 4`
final boolean val = five > four;
if(val) { // Same as `if(5 > 4)`, or `if(true)`
b = 5;
}
For further reading, check out the Java Specs. (Hat tip to Radiodef for finding the right section.)
In this case:
if (false) b = 5; // illegal
The compiler throws an exception since if(false) can be erased at compile time. It is futile to even analyze a block of code that won't be executed by any mean.
In this case:
int a = 5, b;
if (a > 10)
b = 4;
if (a <= 10)
b = 4;
The compiler cannot assure that the piece of code will be executed since a can change its value. In this case, you can fix it by marking a as final and assigning it a literal int value (which compiler can understand):
final int a = 5;
int b;
if (a > 10)
b = 4;
if (a <= 10)
b = 4;
But note that you can still break this code by giving final int a a value that the compiler cannot determine:
final int a = foo();
int b;
if (a > 10)
b = 4;
if (a <= 10)
b = 4;
//...
int foo() {
return 5;
}
More info:
Java Language Specification. Chapter 16. Definite Assignment