Using assignment operator inside of expression - java

Running this code will return 11 while I was expecting 20. Why is that so?
int x = 1;
int y = x + (x = 10);
System.out.println(y);

Evaluation is from left to right. So
int y = x + (x = 10);
is (with x initially 1):
int y = 1 + 10;
Putting the assignment in () doesn't make it come first. It just ensures that it's a valid expression, since y = x + x = 10 would be y = (x + x) = 10 which would require assigning to something (x + x) that wasn't a variable.
If you want 20, put the assignment first:
int y = (x = 10) + x;
Of course, the vast majority of the time, it's best to avoid these kinds of side-effects and assign x a value outside the expression, breaking the expression up if necessary. Assignment-within-expression can be useful sometimes (particularly while ((blah = getNextBlah()) != null) sort of things), but only in limited situations.

Related

Expressing relationship between two variables in pseudocode?

I have some pseudocode I am trying to analyze:
public static void test(float z) {
float y = 0;
for (float i = 1; i <= z; i++) {
if (y < z) {
y = 4 * i * i + 6;
}
}
return y;
}
From the function, I understand that y = 4i^2 + 6 whenever y < z. However, I am having trouble capturing the relationship between y and z in an equation. I feel that it could be captured as a floor function (step function) -- for a certain range of numbers in z, y will have that specified value.
y becomes greater than z (and stops changing) for the first i such that 2*i^2 + 3 > z. In other words, a minimal i > sqrt((z - 3) / 2), which is floor(sqrt((z - 3)/2)) + 1. Now as you know i, compute y.

Java Ternary operator syntax [duplicate]

This question already has answers here:
Ternary operator, syntax error when using assignment
(4 answers)
Closed 8 years ago.
I have the following piece of code. This is how I understand it.
In the first case, the ternary operator returns the value of y because x=4 and the print statement prints 5, as expected.
In the 2nd case, the ternary operator first assigns the value of y to x and then returns that value. Again, it prints 5, as expected.
In the 3rd case, the ternary operator has x=y to the left of the : and x=z to the right of the :. I would expect this to behave much like the 2nd case. However, this statement does not even compile.
Any help in understanding this will be much appreciated.
public class Test {
public static void main(String[] args) {
int x = 4;
int y = 5;
int z = -1;
x = (x == 4) ? y : z; // compiles and runs fine
System.out.println(x + " " + y + " " + z);
x = (x == 4) ? x = y : z; // compiles and runs fine
System.out.println(x + " " + y + " " + z);
x = (x == 4) ? x = y : x = z; // Does not compile
System.out.println(x + " " + y + " " + z);
}
}
Assignment has lower precedence than a ternary expression, so this expression:
(x==4)?x=y:x = z;
can be thought of as:
((x==4)?x=y:x) = z;
Which obviously won't compile because you can't assign a value to something that isn't a variable.
Add parenthesis to control the order of evaluation
x = (x == 4) ? (x = y) : (x = z); // Does compile.
Note the above is equivalent to
if (x == 4) {
x = (x = y);
} else {
x = (x = z);
}
Which will (as a side effect) of assigning a value to x assign the value assigned to x to x. In other words, your ternary is equivalent to
x = (x == 4) ? y : z;
or
if (x == 4) {
x = y;
} else {
x = z;
}
The ternary is specified in JLS-15.25. Conditional Operator ? :.

Java, Understanding

I have the following questions, about this Java Code:
public static void main(String[] args) {
int A = 12, B = 24;
int x = A, y = B;
while (x > 0) {
y = y + 1;
x = x - 1;
}
System.out.println("the solution is " + y);
}
What is beeing computed here?
My solution is, that it's (12-1)+(24+1) = 36. Please correct me if it's the wrong though.
For which A and B there will be an error?
Honestly, i though about A = 1 and smaller, but it didn't work....can someone help me out?
If there's an error, what is the readout?
I could not answer this, as trying out to get an error (for example setting A = -24) i just did not get an error but another solution.
Incrementing y, x times
There'll be no errors for any A and B. In the "worst" case, the loop won't be executed and the initial value of y will be printed
Irrelevant
I don't understand your title, there's nothing to do with String[] args here.
I'm unsure what's the purpose of this code, even for learning purposes..
Let's check this bit of your code:
while (x > 0) {
y = y + 1;
x = x - 1;
}
System.out.println("the solution is " + y);
This is a loop. A while loop, to be precise.
A loop will continue to iterate until the condition of the loop is false
In this case, you have x = 12 and y = 24. Since x value is positive, so it will enter the loop, and continue the calculation for each iterations.
Here are the results you'll get for each iteration:
x = 11, y = 25
x = 10, y = 26
x = 9, y = 27
x = 8, y = 28
x = 7, y = 29
x = 6, y = 30
x = 5, y = 31
x = 4, y = 32
x = 3, y = 33
x = 2, y = 34
x = 1, y = 35
x = 0, y = 36
When you get x = 0 and y = 36, the loop stops, because x = 0 and it violates the condition. So you get out of the loop. The last value of y is 36. That's what you're getting in you println(); it's not x + y, it's y alright.
But when x = -12, or x=-24 or any other negative number, the while condition is false. Your println() is outside the loop, so it will display the value of y which is outside the loop, i.e. 24.
You won't get an error for condition of while being false. Even if you println() x or y inside the loop, you won't get any result, but won't get any error either.
sum of A and B
when A<0 the sum is not calculated correctly
readout is B when there is error

Cause of comparing long slower than comparing double

I wrote a little program to calculate the first 18 triples (x,y,z) with x<y<z, which satisfy x^3+y^3=z^3+1.
While playing around to optimise the total runtime, I discovered, that using double for the cubic values and the two sides of the equation is faster than using long. On my machine the difference is about 3 seconds.
Now I wonder why exactly this is the case. I guess it is somewhere in the internal handling of long while the comparison of two long-Variables, as this is the only thing, which changes within the calculation loops.
Here is my code:
class Threes {
public static void main(String[] args) {
System.out.println("Threes --- Java");
int Z_MAX = 60000, Y_MAX = Z_MAX-1, X_MAX = Y_MAX-1;
double[] powers = new double[Z_MAX+1];
for (int i = 0; i <= Z_MAX; i++) {
powers[i] = Math.pow(i, 3);
}
System.out.println("Powers calculated");
int x, y, z;
double right, left;
int[][] sets = new int[18][3];
int foundCount = 0;
long loopCount = 0;
long start, end;
start = System.currentTimeMillis();
for (x = 1 ; x < X_MAX; x++) {
for (y = x + 1; y < Y_MAX; y++) {
right = powers[x] + powers[y];
for (z = y + 1; z < Z_MAX; z++) {
left = powers[z] + 1;
if (right < left) {
z = Z_MAX;
} else if (right == left) {
sets[foundCount][0] = x;
sets[foundCount][1] = y;
sets[foundCount][2] = z;
foundCount++;
end = System.currentTimeMillis();
System.out.println("found " + foundCount + ". set:\t" + x + "\t" + y + "\t" + z + "\t" + ((end - start) / 1000.0));
if (foundCount == 18) {
x = X_MAX;
y = Y_MAX;
z = Z_MAX;
}
}
loopCount++;
}
}
}
System.out.println("finished: " + loopCount);
}
}
The lines I changed are:
double[] powers = new double[Z_MAX+1];
becomes
long[] powers = new long[Z_MAX+1];
and
powers[i] = Math.pow(i, 3);
becomes
powers[i] = (long)Math.pow(i, 3);
and
double right, left;
becomes
long right, left;
"Bonus Question": What other possibilities of optimizing the whole code in terms of total runtime do I have? I know, that leaving out the loopCount gives me some milliseconds. I'm sure, that I have to reduce the number of loop iterations significantly. But how?
If you are using 32-bit operating system the performance for long-variable could be worse because long is 64-bit type. For example, with 64-bit OS Java could do the comparison with just one machine instruction, but in 32-bit environment it has to use multiple machine instructions, since it can only handle 32-bit at the time.
But for double, this is not neccessary the case, since 32-bit systems have machine instructions for 64-bit floating point numbers, even when thet don't have them for 64-bit integers.
Also, with code:
powers[i] = (long)Math.pow(i, 3);
there is two unneccesary conversions, first i (integer) is converted to double (that's what Math.pow takes) and then the return value is converted back to 64-bit integer (long).
It's probably fair to say that your code spends most of its time in this section:
for (z = y + 1; z < Z_MAX; z++) {
left = powers[z] + 1;
if (right < left) {
z = Z_MAX;
}
And most of the time, it will always be taking the same branch out of the conditional. So once your code has reached the steady-state (i.e. once the CPU's branch predictor is set up), the run-time will be dominated by the computation itself: dependencies are minimised, so the latency of the instruction pipeline doesn't matter.
On a 32-bit machine, doing addition and comparison on 64-bit integer types takes more instructions than doing the equivalent on doubles. A double calculation will take more cycles to complete, but that doesn't matter. We're dominated by instruction throughput, not latency. So the overall run-time will be longer.
In terms of further optimization, you could move the +1 outside the inner loop, by calculating right = powers[x] + powers[y] - 1. But it's possible the optimizer has already spotted that.
Your biggest "bonus" optimization will be to replace the z loop with a calculation like:
z = Math.round(Math.pow(left - 1, 1./3));
and check if z > y && left == powers[(int)z] + 1.
Other improvements if you wanted to find all triples within your limits:
start x at 2 instead of 1
replace z = Z_MAX; with break; to exit the loop early
compute X_MAX as Math.pow((powers[Z_MAX] + 1)/2, 1./3) ~= Z_MAX * Math.pow(0.5, 1./3) since if x is bigger than that, z will exceed Z_MAX
recompute Y_MAX for each x as Math.pow(powers[Z_MAX] - powers[x] + 1, 1./3)/2
BTW, a more common way to order the triples would be using z as the primary sort key, which may result in a different first 18 than you get ordering by x first. To change that, you'd make your outer loop iterate over z, which would be simpler anyway:
for (z = 1; z < Z_MAX; z++) {
for (y = 1; y < z - 1; y++) {
zy = powers[z] - 1 - powers[y];
x = Math.round(Math.pow(zy, 1./3));
if (x < y && zy == powers[(int)x])
...report triple found;
}
}

Pre and postincrement java evaluation

Could you explain step by step how java evaluates
1) the value of y ?
int x = 5;
int y = x-- % x++;
2) the value of y in this case?
int x = 5;
int y = x-- * 3 / --x;
Well, the operands are evaluated from left to right, and in each case the result of a postfix operation is the value of the variable before the increment/decrement whereas the result of a prefix operation is the value of the variable after the increment/decrement... so your cases look like this:
Case 1:
int x = 5;
int tmp1 = x--; // tmp1=5, x=4
int tmp2 = x++; // tmp2=4, x=5
int y = tmp1 % tmp2; // y=1
Case 2:
int x = 5;
int tmp1 = x--; // tmp1=5, x=4
int tmp2 = 3;
int tmp3 = --x; // tmp3=3, x=3
int y = tmp1 * tmp2 / tmp3; // y = 5
Personally I usually try to avoid using pre/post-increment expressions within bigger expressions, and I'd certainly avoid code like this. I find it's almost always clearer to put the side-effecting expressions in separate statements.
I'm not sure about java but in C it evolved into undefined behaviour.

Categories

Resources