Java移位陌生 [英] Java bitshift strangeness
问题描述
Java具有2位移位操作符,用于右移:
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
这似乎很简单,所以任何人都可以向我解释为什么这个代码,当给出一个值为-128的bar时,为foo生成一个值-2:
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);
这是要做一个8位字节,最左边2位的掩码,他们进入最右边的2位。即:
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
结果实际上是-2,这是
The result actually is -2, which is
0b11111110
1而不是零转移到左侧位置
Ie. 1s rather than zeros are shifted into left positions
推荐答案
这是因为&实际上正在执行升级到 int
- 这留下了很多1位。然后你正在向右移动,最左边的2位为0,然后忽略那些最左边的位被转回到字节。
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.
当你分离出操作:
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);
}
}
打印
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
即使你得到正确的结果,操作(通过此时的转换),>>>
将首先将第一个操作数提升到 int
。
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.
编辑:解决方案是改变你如何掩饰事物。而不是屏蔽-64,掩码只是128 + 64 = 192 = 0xc0代替:
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);
这样,你真的只需要两位你想要的,而不是加载1s在最重要的24位。
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.
这篇关于Java移位陌生的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!