有符号和无符号右移似乎具有相同的行为

时间:2019-05-07 08:57:52

标签: java

为什么对于负数,无符号右移(逻辑右移)和有符号右移(算术右移)为什么都产生相同的结果?

Log.v("-59 >>> 5 expected 6, actual", String.valueOf((byte)(-59 >>> 5)));
Log.v("11000101 >>> 5 expected 00000110, actual",Integer.toBinaryString( -59 >>> 5));
Log.v("11000101 >> 5 expected 00000110, actual",Integer.toBinaryString( -59 >> 5));

Android Studio Logcat输出

-59 >>> 5 expected 6, actual: -2

11000101 >>> 5 expected 00000110, actual: 111111111111111111111111110

11000101 >> 5 expected 00000110, actual: 11111111111111111111111111111110

2 个答案:

答案 0 :(得分:1)

这是正常现象。任何具有负值的整数都具有以1s开头的二进制表示形式。

因此,如果您首先说:-3二进制表示形式如下:

...11 1101

因此,如果我们将其右移2,我们将得到

...11 1111

现在开始未标记/右移。这取决于我们的整数中没有无限位数的事实。所以说我们有一个分配为-3的8位整数,它看起来像这样:

1111 1101

如果我们进行有符号移位,它将查看MSB(最高有效位,最左位),并在移位时保留该值。因此,按3号右移的符号移位如下所示:

1111 1111

相反,无符号右移将不会检查MSB,而只会右移并用零填充,结果是:

0011 1111

这正是您所看到的,但是输出会截断前面的零。


如果您不知道为什么以这种方式存储负整数,请check this answer


关于(b & 0xff) >>> 5为何表现不同

java中的整数是32位,这意味着二进制表示形式将具有32位数字。您的-59将类似于以下二进制表示形式:

1111 1111 1111 1111 1111 1111 1100 0101 == -59
0000 0111 1111 1111 1111 1111 1111 1110 == -59 >>> 5

如果现在与0xff一起,您将获得以下信息:

1111 1111 1111 1111 1111 1111 1100 0101 == -59
0000 0000 0000 0000 0000 0000 1111 1111 == 0xff
0000 0000 0000 0000 0000 0000 1100 0101 == -59 & 0xff
0000 0000 0000 0000 0000 0000 0000 0110 == (-59 & 0xff) >>> 5

答案 1 :(得分:0)

右移运算符:-如果数字为负数,则用1填充。如果数字为正数,则用0填充。 无符号移位运算符:-填充0,与数字的符号无关。