位操作-在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的二进制格式如下所示。

11111111111111111111111111010 = -37 (in decimal format)

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

000111111 11111111 11111011 = 536870907(十进制格式).

然而,如果我们应用无符号右移-3(-37>>> -3),我们得到结果7。我不明白它为什么返回7。有人能给我解释一下吗?

这似乎是违反直觉的,但是当移动int时,只使用移位量的最后5位,根据JLS,第15.19节。

如果左操作数的提升类型为int,则只使用右操作数的最低五位作为移位距离。这就好像右操作数受到了位逻辑与操作符&(§15.22.1),掩码值为0x1f (0b11111)。因此,实际使用的移位距离始终在0到31的范围内,包括。

这意味着-3只使用最后5位,或者29。以下是-3的比特,以显示发生了什么:

11111111 11111111 11111111 11111101

后5位是1110129的十进制形式。

右移距离为29,这意味着前3位被保留并一直向右移动。取-37:

11111111 11111111 11111111 11011010

无符号移位29位后,7剩余:

00000000 00000000 00000000 00000111

正如您所看到的,负的移位量充其量是令人困惑的。尽量避免这种情况,并始终尝试使用0到31之间的实际数字作为移位int s的移位量。

最新更新