So I've got 3 ints, 2 of them are only from 0 to 15 (x and z) and 1 (y) goes from 0 to 255. I've been trying to use bit shift with something like this
compressed = (short) (x>>12|y>>8|z);
but it only gets the z value?
Whats the proper way to do this
You need to use the shifts in the other direction, use brackets as shift has low precedence.
compressed = (short) ((x << 12) | (y << 8) | z);
You are shifting the wrong direction:
compressed = (short) ((x<<12) | (y<<4) | z);
Related
I have to write a function that does a left circular shift of the bits of y positions.
For example, if I put: 01011000 and 2 as the y, the function has to return 01100001.
I have tried to use Integer.rotateLeft() but it seems to be useless for this.
This should work I think:
int rotate_8bits_left(int val, int y) {
// amend y to the range [0, 7] with this:
// y = ((y % 8) + 8) % 8;
// or better, with this:
y = y & 0x7;
// do the rotation
return ((val << y) & 0xFF) | (val >> (8-y));
}
Let's explain the different parts:
// move val left y bits:
(val << y)
Above however keeps the bits that get beyond the 8th bit, so we need to truncate them, so we go with:
// move val left y bits and truncate anything beyond the 8th bit:
(val << y) & 0xFF
Now we need to add the bits that went out, to the beginning. We can calculate the bit that went out to the left by just moving to the right:
// move to the right, 8-y bits
val >> (8-y)
If we now glue together the two parts, we would get the rotation:
int new_val = ((val << y) & 0xFF) | (val >> (8-y));
Now for the first part, we want to handle y that might not be in the range [0, 8]. We can amend y to this range, before using it, with:
y = ((y % 8) + 8) % 8;
The expression above fixes both negative and positive values of y, if y is negative the modulo would return a negative value in the range [-7, -1], then by adding 8 we get back to the positive range. We have to do modulo again, for the case where y was positive and adding 8 to fix the negative case took it back to be above 8. The second modulo fixes this.
But we can achieve the same amendment for y with a more simple approach, by leaving only the 3 first bits that encounter for the range [0, 7], treating 8 as 0, this can be done with the following expression, that works well for both negative and positive values of y:
y = y & 0x7;
Trying to store three integers into one to use for a hash, and decode back into their original values.
The variables:
x = 3 byte integer (Can be negative)
z = 3 byte integer (Can be negative)
y = 2 byte integer (Cannot be negative)
My current code - doesn't work with negatives:
long combined = (y) | (((long) z) << 16) | ((((long) x)) << 40);
int newX = (int) (combined >> 40); // Trim off 40 bits, leaving the heading 24
int newZ = (int) ((combined << 24) >> (40)); // Trim off 24 bits left, and the 16 bits to the right
int newY = (int) ((combined << 48) >> 48); // Trim off all bits other then the first 16
It doesn't work for negatives because your "3 byte integer" or "2 byte integer" is actually a regular 4-byte int. If the number is negative, all the highest bits will be set to "1"; if you binary-or the numbers together, these high 1 bits will overwrite the bits from the other numbers.
You can use bit-masking to encode the number correctly:
long combined = (y & 0xffff) | (((long) z & 0xffffff) << 16) | ((((long) x & 0xffffff)) << 40);
This will cut off the high-bits outside the 16 or 24 bit range that you're interested in.
The decoding already works fine, because the bit-shifting that you perform takes care of sign-extension.
Java Integer class has the static method highestOneBit method which will return a value with a single one-bit, in the position of the highest-order one-bit in the specified value, or zero if the specified value is itself equal to zero.
For example input of int 17 will return 16; As 17 can be represented in binary as 10001 so it will return the furthest bit left which is equal to 16.
And in Integer class it has the following implementation in Java doc.
public static int highestOneBit(int i) {
// HD, Figure 3-1
i |= (i >> 1);
i |= (i >> 2);
i |= (i >> 4);
i |= (i >> 8);
i |= (i >> 16);
return i - (i >>> 1);
}
I just want to know the logic behind implementing it this way and the logic behind using shift operations
. Can any one put some light on it.
This algorithm calculates for a given i whose binary representation is:
0..01XXXXXXX...XXXX
the value
0..011111111...1111
That's what the 5 |= operators do.
Then, in the return statement, it subtracts from it that value shifted right by one bit
0..001111111...1111
to get the result
0..010000000...0000
How does it work:
The highest possible 1 bit the the 32nd (left most) bit. Suppose the input number has 1 in that bit:
1XXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
You or that value with the value shifted right by 1 (i >> 1) and get
11XXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
Then you or that new value with the value shifted right by 2 (i >> 2) and get
1111XXXX XXXXXXXX XXXXXXXX XXXXXXXX
Then you or that new value with the value shifted right by 4 (i >> 4) and get
11111111 XXXXXXXX XXXXXXXX XXXXXXXX
Then you or that new value with the value shifted right by 8 (i >> 8) and get
11111111 11111111 XXXXXXXX XXXXXXXX
Finally you or that new value with the value shifted right by 16 (i >> 16) and get
11111111 11111111 11111111 11111111
If the highest 1 bit is smaller than the 32nd bit, these operations still turn all the bits to the right of it to 1 and keep the remaining (higher bits) 0.
The i |= statements help to compute a sequence of ones that is the same length as i. For example, for 101011 it computes 111111. I've explained how it works in this answer (I can't retype it right now since I am on mobile).
So basically, once you have the string of ones, subtracting itself shifted right one bit gives the H.O. bit.
111111 - (111111 >>> 1) = 111111 - 011111 = 100000
The first five lines (i |= (i >> x)) will set every bit below the highest 1-bit to 1. Then, the final line will subtract every 1-bit below the highest one, so that only the highest 1-bit will remain.
For simplicity, let's pretend an int was 8 bits. The code would in that case be like this:
public static int highestOneBit(int i) {
i |= (i >> 1);
i |= (i >> 2);
i |= (i >> 4);
return i - (i >>> 1);
}
Now, let's say we have the value 128 (10000000). This is what would happen:
// i == 10000000
i |= (i >> 1); // i = 10000000 | 11000000 = 11000000
i |= (i >> 2); // i = 11000000 | 11110000 = 11110000
i |= (i >> 4); // i = 11110000 | 11111111 = 11111111
return i - (i >>> 1); // 11111111 - 01111111 = 10000000
The >> is an arithmetic right shift, so it will preserve the signed bit.
The last >>> is a logical right shift, which will not preserve the signed bit. It will always insert zeroes on the left side.
Now, let's try with 64 (01000000):
// i == 01000000
i |= (i >> 1); // i = 01000000 | 00100000 = 01100000
i |= (i >> 2); // i = 01100000 | 00011000 = 01111000
i |= (i >> 4); // i = 01111000 | 00000111 = 01111111
return i - (i >>> 1); // 01111111 - 00111111 = 01000000
Problem and solution:
/** Return the result of swapping the two lower-order bytes of X.
* For example, if X is 0x12345678, then swap(X) is 0x12347856. */
static int swapLower(int X) {
/* Solution */
int lower = X & 0x0000ffff;
int upper = X & 0xffff0000;
return upper | (0xffff & ((lower << 8) | (lower >> 8)));
}
I am confused about how to understand the solution. I tried working through the logic but I did not understand.
Also, I don't know how to come up with the solution in the first place!
EDIT:
Properties:
x & 1 = x
x & 0 = 0
x | 1 = 1
x | 0 = x
int lower = X & 0x0000ffff = X & 0b00000000000000001111111111111111 = 0b0000000000000000x15 ... x0
int upper = X & 0xffff0000 = X & 0b11111111111111110000000000000000 = 0bx31 ... x160000000000000000
lower << 8 = 0b0000000000000000x15 ... x0 << 8 = 0b00000000x15 ... x000000000
lower >> 8 = 0b0000000000000000x15 ... x0 >> 8 = 0bssssssss00000000x15 ... x8
(assuming X is a signed number, then s is the sign bit; it's 0 if X is positive and 1 if X is negative)
(lower << 8) | (lower >> 8) = 0b00000000x15 ... x000000000 | 0bssssssss00000000x15 ... x8 = 0bssssssssx15 ... x0x15 ... x8
0xffff & ((lower << 8) | (lower >> 8)) = 0b000000000000000001111111111111111 & 0bssssssssx15 ... x0x15 ... x8 = 0b00000000000000000x7 ... x0x15 ... x8
upper | (0xffff & ((lower << 8) | (lower >> 8))) = 0bx31 ... x160000000000000000 | 0b00000000000000000x7 ... x0x15 ... x8 = x31 ... x16x7 ... x0x15 ... x8
Yes, That's harder to understand than necessary.
I think this is easier to understand:
int lowest2 = (X & 0x000000FF) << 8; // lowest byte moved 8 bits left
int nextLowest2 = (X & 0x0000FF00) >> 8; // next lowest byte move 8 bits right
int upper4 = (X & 0xFFFF0000);
return upper4 | lowest2 | nextLowest2;
Then when X = 0x12345678:
upper4 | lowest2 | nextLowest2 = 0x12340000 | 0x00007800 | 0x00000056;
But of course if you analyse the solution you gave you get the same thing:
If upper and lower are defined as:
int lower = X & 0x0000FFFF
int upper = X & 0xffff0000;
Then:
X = 0x12345678
lower = 0x00005678
(lower << 8) = 0x00567800
(lower >> 8) = 0x00000056
((lower << 8) | (lower >> 8)) = 0x00567856
(0xFFFF & ((lower << 8) | (lower >> 8))) = 0x00007856
upper = 0x12340000
upper | (0xffff & ((lower << 8) | (lower >> 8))) = 0x12345678
The given solution is correct, but overly complicated and thus more difficult to understand than necessary. The following solution is much easier to comprehend:
return X & 0xffff0000 | ((X & 0xff00) >> 8) | ((X & 0xff) << 8);
It simply pulls three parts out of the number and rearranges them. To understand it, think about each |-separated component, considering what part of the number it selects and where that part ends up in the result.
How do you store 3 numbers in a single byte using bit shifting in java, ie use the first 3 bits for R, the next 3 bits for G, and the last 2 bits B. I think I know how to retrieve the numbers from the bytes, however an example with encoding and decoding would be great.
Thanks Jake
EDIT:
The range of the values for R and G would be 0-7 and 0-3 for B.
Given r, g and b are in the range 0 - 255:
rgb = (b >>> 6) << 6 | (g >>> 5) << 3 | (r >>> 5);
This is filling out the result in this order:
+--+--+--+--+--+--+--+--+
|B7|B6|G7|G6|G5|R7|R6|R5|
+--+--+--+--+--+--+--+--+
i.e. I've assumed that when you've said "first" you meant least significant. If you want them the other way around it would be:
rgb = (b >>> 6) | (g >>> 5) << 2 | (r >>> 5) << 5;