对于Java中的整数,为什么-1为零填充右移1 = 2147483647?

对于以下程序:

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呢?

下图更清楚地说明了我的问题:

样本图片

无符号右移运算符“>>>”将零移动到最左侧位置,而“>>”之后的最左侧位置取决于符号扩展。

因此,-1向右移位一位,具有零扩展,这意味着它将向最左侧位置插入0。 记住,我们在这里处理两个补码 :

-1为: 11111111111111111111111111111111或hex为0xFFFFFFFF

-1 >>> 1是hex中的011111111111111111111111111111110x7FFFFFFF
这是2 31 – 1 == 2147483647

这是移位运算符的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

32位十进制( 二进制补码 )值-1为hex的0xFFFFFFFF。 如果你执行无符号右移( >>> ),则得到0x7FFFFFFF,即2147483647十进制。

你的困惑来自于(非常常见的)误解,即2s补码中有一个“符号位”。 事实并非如此。 最左边的位,也称为最有效位(MSB),有效地贡献了数字的值。

在2s补码表示法中,该位仅表示数字的符号。 但操纵那个位并不能简单地改变符号。

机器内部int格式的另一个值得注意的属性是您不需要将它们解释为带符号的数字。 实际上,这正是您在使用>>>运算符时所执行的操作:您将数字解释为未加数的数字(尽管有“Java没有无符号整数”的神话)。 因此:

 0xffffffff >>> 1 == 4294967295 / 2 

这就是你的结果有意义的方式。 (注意,您不能在Java源代码中编写上述内容,它会抱怨deciaml编号“超出范围”。)

具有真符号位的数据类型是IEEE浮点数。

有符号整数值中最左边的位用于表示天气数量为正(0)或负数(1)。 -1表示为所有位: 11111111111111111111111111111111 。 如果你用>>>将它向左移动,你得到01111111111111111111111111111111这是最高的正数2 ^ 31 – 1 = 2147483647