对于以下计划:
public class ZeroFillRightShift
{
public static void main(String args[])
{
int x = -1;
int y = x>>>1;
System.out.println("x = " + x);
System.out.println("y = " + y);
}
我得到如下输出:
x = -1
y = 2147483647
我得到-1>>>1
的结果是2147483647.如果是必须移位的符号位,就像我所知,结果应该是1073741824.为什么它是2147483647呢?
下图更清楚地说明了我的问题:
答案 0 :(得分:8)
无符号右移运算符“>>>”将零转换为 最左边的位置,而“>>”后的最左边的位置依赖于取决于 签署延期。
因此,-1向右移位一位,具有零扩展,这意味着它将在最左边的位置插入0。请记住,我们在这里处理two's complement:
-1是:11111111111111111111111111111111
或0xFFFFFFFF
在十六进制中
-1>>> 1是Hex中的01111111111111111111111111111111
或0x7FFFFFFF
,其中2 31 - 1 == 2147483647
这是shift operators的JLS参考。
你似乎对两个人的补充感到困惑。 31位用于值,最左边的位用于符号。由于您只移位1位,因此有符号位变为0,这意味着为正,结果是最大正数而不是int
可以表示的。
也许另一个例子会有所帮助。让我们考虑以下几点:
System.out.println(-2 >> 1); //prints -1
-2 = 11111111111111111111111111111110
如果我们使用带符号的右移,我们得到:11111111111111111111111111111111
,即-1。但是,如果我们这样做:
System.out.println(-2 >>> 1); //prints 2147483647
因为-2 = 11111111111111111111111111111110
并执行无符号右移,这意味着我们将零位扩展移位1位,给出:01111111111111111111111111111111
答案 1 :(得分:4)
32位十进制(two's complement)值-1为十六进制的0xFFFFFFFF。如果你执行无符号右移(>>>
),则得到0x7FFFFFFF,即2147483647十进制。
答案 2 :(得分:2)
你的困惑来自于(非常常见的)错误观念,即2s补语中有一个“符号位”。事实并非如此。最左边的位,也称为最有效位(MSB),有效地贡献了数字的值。
在2s补码表示法中,该位仅表示数字的符号。但操纵那一位并不能简单地改变这个标志。
机器内部int格式的另一个值得注意的属性是您不需要将它们解释为带符号的数字。实际上,这正是您在使用>>>
运算符时所执行的操作:您将数字解释为未加数的数字(尽管有“Java没有无符号整数”的神话)。因此:
0xffffffff >>> 1 == 4294967295 / 2
这就是你的结果有意义的方式。 (请注意,您不能在Java源代码中编写上述内容,它会抱怨deciaml编号“超出范围”。)
具有真符号位的数据类型是IEEE浮点数。
答案 3 :(得分:1)
有符号整数值中最左边的位用于表示天气数字为正(0)或负数(1)。 -1表示为11111111111111111111111111111111
上的所有位。如果您使用>>>
向左移动,则得到01111111111111111111111111111111
这是最高的正数2 ^ 31 - 1 = 2147483647