在Java中,当使用位移时,为什么1<< 32!= 1<< 31<< 1?

时间:2009-03-31 19:14:34

标签: java bit-manipulation

int a = 1 << 32; int b = 1 << 31 << 1;

为什么a == 1? b是我预期的0。

2 个答案:

答案 0 :(得分:23)

对于整数,所有的班次都是mod 32,对于long是mod 64。

来自section 15.19 of the spec

  

如果是左手的提升类型   操作数是int,只有五个   右手的最低位   操作数用作移位   距离。就好像是右手   操作数受到一点点的影响   逻辑AND运算符&amp; (§15.22.1)with   掩码值0x1f。调动,转移   因此实际使用的距离   总是在0到31的范围内,   包容。

     

如果是左手的提升类型   操作数是long,然后只有六个   右手的最低位   操作数用作移位   距离。就好像是右手   操作数受到一点点的影响   逻辑AND运算符&amp; (§15.22.1)with   掩码值0x3f。调动,转移   因此实际使用的距离   始终在0到63的范围内,   包容。

至于为什么语言是这样设计的 - 我不知道,但C#有相同的设计决定。以下是带注释的ECMA C#规范所说的内容:

  C#故意保留   实现定义的行为   miinimum。只有当他们被接受时   强迫对性能的影响   统一的行为会过分   (比如某些浮点数   精度问题)。因此,大小   每种积分类型都是精确的   指定,字符集是   固定为Unicode。

     

对于轮班操作,也是统一的   行为已指定。有可能   使用一个额外的   指令(&amp; 0x1F或&amp; 0x3F)即   现代只需要很小的成本   处理器,特别是因为它   不是参考记忆。与...不同   浮点运算,   转变行为的差异将是   如果留下一时兴起的戏剧性   处理器;而不是一个小的   精度差异,完全   不同的积分结果将是   产生的。

     

在做出这个决定的时候   研究了参考资料   不同处理器的数量   架构。几乎没有   转变行为的一致性   计数超出-32 .. + 32的范围   32位操作数,分别为   -64 .. + 64位64位操作数。

(然后列出一些例子。)

这对我来说似乎是一个完全合理的解释。一致性肯定是重要的,如果在某些系统上以高效的方式实现不同的一致行为,我认为这是一个合理的解决方案。

答案 1 :(得分:0)

处理器实现转换指令的方式有所不同。

例如,IIRC,ARM处理器(32位ISA)占用移位寄存器的最低有效字节。 (班次实际上并不是ARM上的独立指令)。

只要底层处理器有一种模糊的移位方式,就可以更容易地清除除最低有效位之外的所有位(通常是一条指令),而不是检查移位是否很大和分支(实际上在ARM上这只是典型的)添加一条指令,因为所有指令都是有条件的。)