【问题标题】:unsigned right shift by negative number in Java [duplicate]Java中无符号右移负数[重复]
【发布时间】:2026-01-23 22:30:01
【问题描述】:

我很难理解负无符号位运算符。 例如,我有下面的代码。它打印出值 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。有人可以向我解释一下吗?

【问题讨论】:

    标签: java bit-manipulation bit-shift


    【解决方案1】:

    这似乎违反直觉,但是根据JLS, Section 15.19,移位int 时,仅使用移位量的最后5 位。

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

    这意味着-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 的移位量。

    【讨论】:

    • 感谢您的解释以及何时不使用它们的提示。我只是在玩按位运算符,并试图更好地理解它们的工作原理。我猜负无符号右移(这听起来很奇怪)只会使代码更难理解,而且从你的解释中确实有意义。