java位是否循环变换?
我有这种使用Java的行为:
int b=16; System.out.println(b<<30); System.out.println(b<<31); System.out.println(b<<32); System.out.println(b<<33);
输出:0 0 16 32
java位移位是圆形的吗? 如果没有,为什么我在b << 30和16时b <32时得到0?
位移不是循环的; 对于位移int
s,Java仅使用5个最低有效位,因此(b << 0)
等价于(b << 32)
(相当于(b << 64)
等)。 您可以简单地取位移量并在除以32时取余数。
对于long
位s的位移会发生类似的事情,其中Java仅使用6个最低有效位,因此(aLong << 0)
等效于(aLong << 64)
。
JLS第15.19节谈到了这一点:
如果左侧操作数的提升类型是int, 则只使用右侧操作数的五个最低位作为移位距离。 就好像右手操作数受到按位逻辑AND运算符&(§15.22.1)和掩码值0x1f(0b11111)的影响。 因此,实际使用的移位距离始终在0到31的范围内,包括0和31。
如果左侧操作数的提升类型很长, 则只使用右侧操作数的六个最低位作为移位距离。 就好像右手操作数受到按位逻辑AND运算符&(§15.22.1)和掩码值0x3f(0b111111)的影响。 因此,实际使用的移位距离总是在0到63的范围内,包括0和63。
(强调我的)
(你不能对float
或double
位进行位移,并且尝试对一个short
或一个byte
进行位移会使值无论如何都要将一元数字提升的值赋予int
。)
从16 << 30
得到0
,因为16
位的1位
00000000 00000000 00000000 00010000
从int
的末尾移开并被丢弃。
// Discarded - Result----------------------------- (00000100) 00000000 00000000 00000000 00000000
不,这不是循环转变。 这是正常的左移。 只是,对于int
类型左侧操作数,Java仅使用右操作数的5个低位来进行移位。 这符合JLS§15.9 :
如果左侧操作数的提升类型是int,则只使用右侧操作数的五个最低位作为移位距离。 就好像右手操作数受到按位逻辑AND运算符&(§15.22.1)和掩码值0x1f(0b11111)的影响。 因此,实际使用的移位距离始终在0到31的范围内,包括0和31
因此,对于16 << 32
,仅考虑16 << 32
5个低阶位,表达式相当于:
16 << 32 & 0x1f
等于16。