java - Java中无符号右移负数

标签 java bit-manipulation bit-shift

我很难理解负无符号按位运算符。 例如,我有下面的代码。它打印出值 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 位以向下翻转的状态(从 0 到 1)出现在最左边的位置,这意味着我们得到以下结果。

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 位是十进制的 1110129

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

11111111 11111111 11111111 11011010

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

00000000 00000000 00000000 00000111

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

关于java - Java中无符号右移负数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31306213/

相关文章:

c - 是否有一种节省空间的方法来存储和检索数据集的顺序?

c# - 用 2 的补码表示十六进制值

Java 对无符号整数进行位移

java - 具有相同端口和地址的套接字的两个实例

java - 直接从 URL 读取并写入文件 - Java

assembly - `test` 指令是如何工作的?

c++ - 如何使用移位运算符 << 分配 BH1750 光传感器中的值?

c++ - 右移非整数类型的数字

java - 使用 JTable 放置面板

java - 从没有 JSTL 的 JSP 访问 FlowScope