我很难将头部缠绕在负无符号位运算符周围。 例如,我有以下代码。它打印出值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),据我所知(如果我的理论存在缺陷或缺乏关键,请纠正我概念),它将字节向右移动3,在最右侧位置出现的3位出现在翻转状态的最左侧位置(从0到1),这意味着我们得到以下结果。
00011111 11111111 11111111 11111011 = 536870907(十进制格式)。
但是,如果我们应用-3的无符号右移(-37>>> -3),我们得到结果7.我不明白它为什么返回7.有人请解释一下对我?
答案 0 :(得分:0)
这似乎是违反直觉的,但是当移动int
时,根据JLS, Section 15.19,仅使用移位金额的最后5位。
如果左侧操作数的提升类型为
int
,则只使用右侧操作数的五个最低位作为移位距离。就好像右手操作数受到按位逻辑AND运算符& (§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之间的实际数字来换班int
。