Java 中无符号右移负数

unsigned right shift by negative number in Java

我很难理解负的无符号按位运算符。 例如,我有下面的代码。它打印出值 7,我不明白为什么。

int num1 = -37, num2 = -3;    
System.out.println( num1 >>> num2);
// Essentially the same as System.out.println( -37 >>> -3); 
// I just wanted to emphasize that i am working with Integers

据我所知,二进制格式的数字-37如下所示。

11111111 11111111 11111111 11011010 = -37(十进制格式)

如果我们是 3 的无符号右移(-37 >>> 3,而不是 -37 >>> -3),据我所知(如果我的理论有缺陷或缺乏关键概念,请纠正我),它将字节向右移动 3 位,落在最右侧位置的 3 位以向下翻转状态(从零到一)出现在最左侧位置,这意味着我们得到以下结果。

00011111 11111111 11111111 11111011 = 536870907(十进制格式)。

但是,如果我们应用 -3 的无符号右移 (-37 >>> -3),我们得到结果 7。我不明白为什么返回 7。有人可以解释一下吗我?

这似乎违反直觉,但是根据JLS, Section 15.19.

,当对int进行移位时,只使用移位量的最后5位。

If the promoted type of the left-hand operand is int, then only the five lowest-order bits of the right-hand operand are used as the shift distance. It is as if the right-hand operand were subjected to a bitwise logical AND operator & (§15.22.1) with the mask value 0x1f (0b11111). The shift distance actually used is therefore always in the range 0 to 31, inclusive.

这意味着 -3 只使用了最后 5 位,或 29。下面是 -3 位来显示正在发生的事情:

11111111 11111111 11111111 11111101

最后 5 位是 11101,或十进制的 29

右移距离为29,表示保留前3位,一路右移。服用 -37:

11111111 11111111 11111111 11011010

无符号移位29位后,剩下7

00000000 00000000 00000000 00000111

如您所见,负偏移量充其量只是令人困惑。尽量避免它并始终尝试使用 0 到 31 之间的实际数字作为移位量 ints.