在Core Java Volume1一书中,有一个警告说:
注意:移位运算符的右侧参数以模32减少 (除非左侧是长的,在这种情况下,右侧是模64减少)。 例如,值<&lt;&lt; 35与1&lt; 1&lt; 3或8。
这究竟是什么意思?还有为什么1变为8,而不是在35左移后变为0?
非常感谢答案 0 :(得分:10)
减少模32意味着(在其基级)你保持减去32,直到你有一个0到31之间的数字。
换句话说:
actualValue = givenValue % 32;
原因它这样做是因为将32位值32位向左(或右)移位没有意义,因为总是为零(因为你在一侧移位了比特并且在另一端移动了 - 对32位值执行32次操作将导致零,无论你开始的是什么)
因此对于Java整数(32位),31是合理的限制。对于长(64位),63是合理的限制。
在您提供的示例中,1 << 35
的班次值从35减少到3(从35 % 32 == 3
开始)和1&lt;&lt; 3是8:
Binary
0000 0001 (1 << 0) == 1
0000 0010 (1 << 1) == 2
0000 0100 (1 << 2) == 4
0000 1000 (1 << 3) == 8
||||
|||+--- 1
||+---- 2
|+----- 4
+------ 8
答案 1 :(得分:5)
在许多编程语言中,移位超过数值数据类型的大小(对于int为32位,长为64位)未定义。另一方面,Java定义它使得(n << d)
等同于(n << (d % 32))
,其中n
是int,(n << d)
等同于(n << (d % 64))
其中n
1}}很长。
因此,1 << 35
相当于1 << (35 % 32)
,等于1 << 3 = 8
。
答案 2 :(得分:4)
更简洁
a << b
与
相同a << (b & 31)
表示int类型。
不同之处在于-1%32为-1而-1和-1为-1。 31是31和1 << -1 == 0x80000000
此行为在JLS 15.19
中定义如果左侧操作数的提升类型为int,则只使用右侧操作数的五个最低位作为移位距离。就好像右手操作数受到按位逻辑AND运算符&amp; (§15.22.1),掩码值为0x1f(0b11111)。因此,实际使用的移动距离始终在0到31的范围内,包括0和31。
如果左侧操作数的提升类型很长,则只使用右侧操作数的六个最低位作为移位距离。就好像右手操作数受到按位逻辑AND运算符&amp; (§15.22.1),掩码值为0x3f(0b111111)。因此,实际使用的移位距离始终在0到63之间,包括0和63.