Java has 2 bitshift operators for right shifts:
>> shifts right, and is dependant on the sign bit for the sign of the result
>>> shifts right and shifts a zero into leftmost bits
http://java.sun.com/docs/books/tutorial/java/nutsandbolts/op3.html
This seems fairly simple, so can anyone explain to me why this code, when given a value of -128 for bar, produces a value of -2 for foo:
byte foo = (byte)((bar & ((byte)-64)) >>> 6);
What this is meant to do is take an 8bit byte, mask of the leftmost 2 bits, and shift them into the rightmost 2 bits. Ie:
initial = 0b10000000 (-128)
-64 = 0b11000000
initial & -64 = 0b10000000
0b10000000 >>> 6 = 0b00000010
The result actually is -2, which is
0b11111110
Ie. 1s rather than zeros are shifted into left positions
Bitshifting shifts the binary representation of each pixel to the left or to the right by a pre-defined number of positions. Shifting a binary number by one bit is equivalent to multiplying (when shifting to the left) or dividing (when shifting to the right) the number by 2.
The bitwise shift operators are the right-shift operator ( >> ), which moves the bits of an integer or enumeration type expression to the right, and the left-shift operator ( << ), which moves the bits to the left.
Left shift operator shifts the bits of the number towards left a specified number of positions. The symbol for this operator is <<.
1 in binary is 0001 , then bitshifting it by 0 won't do anything, which aligns with what you observed. So any number x << 0 is equivalent to x * 2^0 , which is x * 1 , which is just x .
It's because the & is actually performing promotion to int
- which leaves an awful lot of "1" bits. You're then shifting right, leaving the leftmost 2 bits as 0, but then ignoring those leftmost bits by casting back to byte.
This becomes clearer when you separate out the operations:
public class Test
{
public static void main(String[] args)
{
byte bar = -128;
int tmp = (bar & ((byte)-64)) >>> 6;
byte foo = (byte)tmp;
System.out.println(tmp);
System.out.println(foo);
}
}
prints
67108862
-2
So to do your bit arithmetic again:
initial = 0b10000000 (-128)
-64 = 0b11000000
initial & -64 = 0b11111111111111111111111110000000 // it's an int now
0b10000000 >>> 6 = 0b00111111111111111111111111100000 // note zero-padding
(byte) (0b10000000 >>> 6) = 11100000 // -2
Even if you get the right result out of the & operation (by casting at that point), >>>
will promote the first operand to int
first anyway.
EDIT: The solution is to change how you mask things. Instead of masking by -64, mask by just 128+64=192=0xc0 instead:
byte foo = (byte)((bar & 0xc0) >>> 6);
That way you really only get left with the two bits you want, instead of having a load of 1s in the most significant 24 bits.
AFAIK, in Java most operators (+,-,>>,& etc.) can't work on anything smaller than int
s. So, your bitwise shifts and &
are implicitly casting the values into int
in the background and then back into byte
by your explicit cast outside. The last cast gets rid of the zeroes in the higher bits.
To get results you would expect, try doing this on int
s.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With