double assignment in single instruction - java

This may sound crazy, but i'm curious to know if it is possible to use a single instruction to modify the values of two different variables.
For example, suppose i have this code (x and y are int variables):
if(x < 0) {
y -= x ;
x = 0;
}
If x is equal to -1, i would obtain the same result by doing the following :
if(x < 0) y -= x++;
Is there a way to generalise the previous result? I tried with the instruction :
if(x < 0) y -=x-=x;
But, while x at the end is equal to 0, y won't be modified. What i'm missing ?
EDIT
I thought (i was wrong probably) it was clear that my question was purely theoretical.
I know that this way of doing should be avoided. I was just curious :).

Try this:
if(x < 0) x = (y -= x) - y;
It's fine to try tricks like these for a challenge. However, Don't use this type of code in your actual code as it'll create confusion for others.

Related

More efficient way to check if a value is included in an array?

Writing a game that does lots of comparisons, and it's lagging. I'm trying to speed it up, and this particular chunk of code is run thousands of times every frame, for different values of x y and z. Is there a better way to check if the values of x y and z are valid in the array? (java)
if (x >= 0 && x < blocksArr.length && y >= 0 && y < blocksArr[x].length && z >= 0 && z < blocksArr[x][y].length && blocksArr[x][y][z])
I've tried checking if blocksArr[x][y][z] != null and checking if blocksArr[x][y][z] != undefined but neither give results.
In general, the most efficient way of doing t >= 0 && t < u with u known to be positive is to compare the unsigned value of t and u using Integer.compareUnsigned(t, u) < 0. As a result, your if can be more efficiently expressed as
if (Integer.compareUnsigned(x, blocksArr.length) < 0 &&
Integer.compareUnsigned(y, blocksArr[x].length) < 0 &&
Integer.compareUnsigned(z, blocksArr[x][y].length) < 0 &&
blocksArr[x][y][z])
However, I think your representation of blocksArr as a 3-dimensional array is really inefficient and results in a lot of indirections, which greatly hinders the potential performance. A more logical approach is to represent it as a single array and have length, width, height being stored separately. This would result in your code looks something like this:
if (Integer.compareUnsigned(x, length) < 0 &&
Integer.compareUnsigned(y, width) < 0 &&
Integer.compareUnsigned(z, height) < 0 &&
blocksArr[x * (width * height) + y * height + z])
This however limits your block to around 2 billion elements, to overcome this limitation, you need to resort to the Memory Access API, which is currently in preview. It has an important advantage that it allows the allocation and deallocation of memory blocks to be deterministic, which is much more desirable for too large memory pieces. Using a memory segment to represent the blocksArr, your code would become:
if (Long.compareUnsigned(x, length) < 0 &&
Long.compareUnsigned(y, width) < 0 &&
Long.compareUnsigned(z, height) < 0 &&
blocksArr.get(ValueLayout.JAVA_BOOLEAN, x * (width * height) + y * height + z))
Moreover, since blocksArr is a block of boolean values, packing them so that each element occupies only 1 bit will improve the memory consumption and cache pressure greatly. The check now can be expressed as:
long index = x * (width * height) + y * height + z;
long byteIndex = index >>> 3;
int shift = (int)(index & 7);
if (Long.compareUnsigned(x, length) < 0 &&
Long.compareUnsigned(y, width) < 0 &&
Long.compareUnsigned(z, height) < 0 &&
blocksArr.get(ValueLayout.JAVA_BYTE, byteIndex) & (1 << shift) != 0)
I don't know java but in general, I would expect the following to be at least as fast, possibly faster.
Your compiler may do something like this anyway so it might not be faster. You can split the 'If' statement up so that it will do fewer lookups. Sorry, but I'll have to write it as c code. You can get the idea and translate to java.
if (x >= 0 && y >= 0 && z >= 0 && x < blocksArr.length) {
if (y < blocksArr[x].length && z < blocksArr[x][y].length && blocksArr[x][y][z]) {
.....
}
}
Assuming user16320675 is correct about the evaluation order, you could use one 'if' statement. I don't know how the java compiler works.
if (x >= 0 && y >= 0 && z >= 0 && x < blocksArr.length && y < blocksArr[x].length && z < blocksArr[x][y].length && blocksArr[x][y][z]) .....
What you are doing is a bounds check, to make sure that the indexes x, y, and z are valid indices in the blocksArr[][][] array. In C, this is necessary as C allows you to go outside the array.
Java, however, does a bounds check every time you access the array. So you are doing a manual bounds check, then another check, plus Java is doing a check on two dimensions, and finally Java does another check on three dimensions.
All you really need to do is access the array, let Java do the bounds check, and catch an exception if any of the indices are out of bounds.
boolean value;
try
{
value = blocksArr[x][y][z];
}
catch (ArrayIndexOutOfBoundsException e )
{
value = false;
}
There is some overhead in setting up a try/catch block, but overall it should be faster.
You have a box determined by three dimensions, x, y, and z.
If any of those indices are outside the boundaries of the box, then the entire if() statement is false. So there is no need to walk through things like blocksArr[x].length
Also, think about what is actually going on under the hood. The variable x is in fact a pointer to a location in memory which holds the value. To process a statement like x >= 0, the computer must locate the memory location for x, fetch that value and put it into one of its internal registers, say register A. It then takes that value 0 and puts it into register B. It compares Register A to register B. if A > B, then it goes on to the next operation, otherwise it compares A to B again. If the comparison is zero, then it goes to the next operation, otherwise it move the operation pointer past the if() statement.
For comparing x < blocksArr.length, it again fetches x, then fetches blocksArr calculates the offset to the length value, then fetches that into the register, where it does the comparison.
You can shorten all of this by using some static constants.
Consider that x >= 0 can be re-written as x > -1. This can potentially reduce 2 comparisons to 1, so a few CPU cycles saved.
An array construct is an immutable object, that is it cannot be changed after being created. So an array's length will never be different. So if you created an array with size 5, blocksArr.length will always return 5. in the comparison x < blocksArr.length you could substitute x < 5, which means the CPU does not need to fetch blocksArr.length, which saves CPU cycles.
So you could re-write the array creation, and your if statement to:
public static final int MAX_X = 10;
public static final int MAX_Y = 15;
public static final int MAX_Z = 20;
public boolean blocksArr[][][] = new boolean[MAX_X][MAX_Y][MAX_Z];
.
.
.
if ( ( x > -1 && x < MAX_X ) && // validate for X dimension
( y > -1 && y < MAX_Y ) && // validate for Y dimension
( z > -1 && z < MAX_Z ) && // validate for Z dimension
blocksArr[x][y][z] ) // check value
I think this is the least CPU intensive way of doing this.

How can I fix the error "This method must return a result of type int" without breaking the current code?

As far as I know, I understand this error. I know that within my program there is a situation where no conditions are met and the computer doesn't know what to do. That being said, I'm not sure how to fix it properly without breaking the current code. I've added a return 0 at the end of all the if statements, which gets rid of the error, but in some cases the 0 prints out which of course I don't want it to. I also tried putting it within an else statement at the very end as-well, but I still get the same error.
Assignment instructions are as follows: "If the two parameters are within 1 of each other, return the smaller number; Otherwise, subtract one from the larger parameter and add one to the smaller parameter and balance the result."
Here is what I have:
public static int balance (int x, int y) {
if(x == y) {
System.out.println("The values X and Y (" + x + " and " + y + ") are already balanced; They are equal to each other!");
}
else if(Math.abs(x-y) == 1) { //Checks to see if numbers are within 1 of each other (Math.abs because negative numbers don't matter in this case)
if(x > y) {
return y;
}
else return x;
}
else if(x > y) {
x = x - 1; //X is larger so we subtract
y = y + 1; //Y is smaller so we add
return balance(x,y); //Recursion happens
}
else if(x < y) {
y = y - 1; //Y is larger so we subtract
x = x + 1; //X is smaller so we add
return balance(x,y); //Recursion happens
}
}
The calculations and everything on that side seem to work exactly like the instructions are asking. I just can't seem to get rid of the "This method must return a result of type int" error without having random values that are unneeded showing up in the console.
You need to make two changes.
Decide what to return in the case where x == y, and add the appropriate return statement to the first branch.
Change else if (x < y) { to else {. You know that you've exhausted all the possibilities, but the compiler doesn't. This is a sure-fire way of telling the compiler that there's nowhere else to end up.
Unless you do these two things, the compiler believes there's a possibility that it could run out of lines to execute in the method, without encountering a return statement. That's not valid for a method that you've declared as returning an int.

Writing Java long If/Else Loops in a shorter way

Hi guys i currently have a assignment which i just finished but their is one detail i dont love about it. Is there a way to shorten if else loops
Currently i have wrote
if (x >=300) {
set y = 1;
}
else if(x >=200) {
set y = 2;
}
else if (x >=150) {
set y = 3;
}
else if (x>=100) {
set y = 4;
}
else if (x >=50) {
set y = 5;
}
else if (x >=25) {
set y = 6;
}
Probably me just being pedantic, thanks in advance
You could shorten it to
y = x>=300 ? 1 : x>=200 ? 2 : x>=150 ? 3 : x>=100 ? 4 : x>=50 ? 5 : 6;
but while that may be more compact, it is also subjectively less readable. For additional informatione, see here.
This looks like a place where you could use the switch statement. However, the switch statement is designed to handle known values rather than inequalities. If you don't like the way the chain of if-else statements looks, you could do it all in an inline expression (Ternary Operator), but that makes it hard to read.
I'd say keep the code the way it is unless there's a good reason to change it. If you're only going to have one code statement after each statement, then you can eliminate the curly braces {} to make the code look a little cleaner:
if (x >= 300) set y = 1;
else if (x >= 200) set y = 2;
else if (x >= 150) set y = 3;
else if (x >= 100) set y = 4;
else if (x >= 50) set y = 5;
else if (x >= 25) set y = 6;

Increment X Mod N in One Line

I have several small programs that require infinitely looping over the integer set Z sub n. I often write the code in this manor:
int x = 0;
int n = 13; //or some other prime
while(1) {
//do stuff dependent on x
++x;
x %= n;
}
I write code mostly in C/C++ & Java so I was wondering:
Is there a way to increment x mod n in one line rather then two in either language?
Have you considered:
x = (x + 1 == n ? 0: x + 1);
The chances are the x + 1 will optimise to one instruction and at least you are guaranteed to never use division (which a bad optimiser might use when % is involved).
x = (x + 1) % n;
Not terribly surprising.
Another alternative is this
x = ++x % n; // Java
if (++x == n) x = 0;
Using x = (x + 1 == n ? 0 : x + 1); requires two additions: one for the comparison and another when the value of x is set to x + 1.

Java logical test questions

I've been solving a few problems about logic tests for AP Computer Science but I happened to get stuck on a few questions.
Here are the directions from the website: Translate each of the following English statements into logical tests that could be used in an if/else statement. Write the appropriate logical test for each statement below. Assume that three int variables, x, y, and z, have already been declared.
These are the 2 questions I have problems with:
Either x or y is even, and the other is odd.
x and z are of opposite signs.
I've been trying to find these answers out for a couple of hours and I still have no clue. I would appreciate it if someone could guide me in the right direction. I understand this is "homework" but some definitive help would be very helpful.
For the first question: x % 2 != y % 2
Second question: x * z < 0
You'll need to use and (&&) and or (||) to make a logic formula. I'm not going to do yours, but here's another one:
x is bigger than both y and z or x is less than both y and z.
Translates to:
((x > y) && (x > z)) || ((x < y) && (x < z))
You just need to figure out a formula for odd/even (hint - the low order bit) and for positive/negative (hint - compare with 0), and combine those with and/or.
For the first question, if x (or y)* is odd, y (or x) must be even, and vice versa. Checking for odd values implies that the modulo of x and 2 is 1 - from there, you would have to assert if y (or x) modulo 2 is 0 (to check for evenness).
For the second question, you would need to follow a chain of logic as such:
X is positive (or greater than 0), which implies Z must be negative (or less than 0).
Z is positive, which implies that X must be negative.
*: This is an exclusive or - I mean that you're either checking x or y, but not both at the same time.
First you have to fully understand the statement in order to put it into the language of a computer. For example,
x and y have the same sign
What this really means is:
( x is greater than or equal to 0 and y is greater than or equal to 0 ) or ( x is less than 0 and y is less than 0 )
Now it is easy to put this into Java:
(x >= 0 && y >= 0) || (x < 0 && y < 0)
Of course, your questions can be solved via a similar method.
Either x or y is even, and the other is odd.
The sum of an odd and even number is odd. The sum of two odd numbers is even and the sum of two even numbers are even.
So (x+y)%2!=0.
x and z are of opposite signs
This one is similar, you can do:
x*z<0
Since 0 is neither negative or positive and
neg * pos = neg
neg * neg = pos
pos * pos = pos
If you want to consider 0 and a negative number of opposite signs you can use (x >= 0) == (z < 0)
Putting it in plain english, for me anyhow.
If ((x is even AND y is odd) OR (x is odd AND y is even))
For the other
If ((x gt or eq 0 AND y lt 0) OR (y gt or eq 0 AND x lt 0))
Assuming 0 is positive.

Categories