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

为什么Java中整数的-1零填充右移1=2147483647?,java,bit-shift,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的

对于以下程序:

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是:
11111111111111111111111
0xFFFFFFFF
十六进制

-1>>>1是以十六进制表示的
011111111111111
0x7FFFFFFF
,即231-1==2147483647

这里有一个JLS参考

你似乎对二的补语感到困惑。31位用于值,最左边的位用于符号。由于只移动1位,有符号位变为0,这意味着正,结果是
int
所能表示的最大正数

也许另一个例子会有所帮助。让我们考虑如下:

System.out.println(-2 >> 1); //prints -1
-2=
1111111111111111111 0

如果我们使用有符号右移,我们得到:
11111111111111111
,即-1。然而,如果我们这样做:

System.out.println(-2 >>> 1); //prints 2147483647

由于-2=
1111111111111111111111 0
并进行无符号右移,这意味着我们以零扩展名移位1位,给出:
011111111111111111
32位十进制()值-1是十六进制的0xFFFFFFFF。如果将无符号右移(
>>
)一位,则得到0x7FFFFFFF,即2147483647十进制数

有符号整数值中最左边的位用于指示数字是正(0)还是负(1)-1表示为上的所有位:
11111111111111
。如果你用
>>
将其向左移动,你会得到
011111111111111111111
,它是最大的正数2^31-1=2147483647

你的困惑源于(非常常见的)错误观念,即2s补码整数中有一个“符号位”。事实并非如此。最左边的位,也称为最高有效位(MSB),积极地贡献数字的值

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

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

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


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

-1不是只设置了符号位的数字,它是Integer.MIN\u值-1是设置了所有位的数字。这是一个问得很好的问题。您忘记了
int
由32位或4个字节组成。2^32-1绝对不是20亿。在2^32-1上执行“预结束0位”右移时,将得到2^31-1。这总是个好主意。@marounnaroun谢谢你的链接。我的问题是为什么会这样?请看我随问题附上的图片。感谢您花时间回答!图像中的错误是假设-1是0x8000001,即有符号数字以符号大小格式存储。实际使用的表示法是二的补码,您可以在我链接的文章中阅读更多关于二的内容。您能展示一个十进制到二进制而不是十六进制到十进制的示例吗?十六进制是一种简洁的二进制表示法。只需将每个
f
替换为
1111
,就可以得到二进制文件。然而,当你对这样的问题感兴趣时,你应该学会用十六进制“思考”。为此,请自己制作一份包含所有16个十六进制数字的二进制表示的小备忘单。过一会儿你就会发现你不再需要它了。
0xffffffff >>> 1 == 4294967295 / 2