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

时间:2013-12-07 09:28:19

标签: java bit-shift

对于以下计划:

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

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

The sample image

4 个答案:

答案 0 :(得分:8)

  

无符号右移运算符“>>>”将零转换为   最左边的位置,而“>>”后的最左边的位置依赖于取决于   签署延期。

因此,-1向右移位一位,具有零扩展,这意味着它将在最左边的位置插入0。请记住,我们在这里处理two's complement

-1是:111111111111111111111111111111110xFFFFFFFF在十六进制中

-1>>> 1是Hex中的011111111111111111111111111111110x7FFFFFFF,其中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