当前位置: 首页 > 面试题库 >

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

赵高韵
2023-03-14
问题内容
int a = 1 << 32;
int b = 1 << 31 << 1;

为什么a == 1呢?b如我所料是0。


问题答案:

所有移位都针对整数进行mod 32,对long进行mod 64。

从规范的第15.19节开始:

如果左侧操作数的提升类型为int,则仅将右侧操作数的最低5位用作移位距离。就像右侧操作数受到掩码值0x1f的按位逻辑AND运算符&(§15.22.1)一样。因此,实际使用的移动距离始终在0到31(含)范围内。

如果左侧操作数的提升类型为long,则仅将右侧操作数的六个最低位用作移位距离。就像右侧操作数受到掩码值0x3f的按位逻辑AND运算符&(§15.22.1)一样。因此,实际使用的移动距离始终在0到63之间(包括0和63)。

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

C#故意将实现定义的行为保持在最低水平。仅当强制执行统一行为对性能的影响过大时(例如,对于某些浮点精度问题),才接受它们。因此,每个整数类型的大小都可以精确指定,并且字符集固定为Unicode。

对于换档操作,也指定了统一的行为。可以使用一条额外的指令(&0x1F或&0x3F)来实现,这条指令在现代处理器上只会产生很小的成本,尤其是因为它不引用内存。与浮点运算不同,如果让处理器心血来潮,则换档行为的差异将非常明显。而不是精度上的微小差异,将产生完全不同的积分结果。

在做出此决定时,委员会研究了许多不同处理器体系结构的参考资料。对于32位操作数,移位计数超出-32 .. + 32范围,对于64位操作数,超出-64
.. + 64范围时,行为几乎没有一致性。

(然后是一些示例的列表。)

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



 类似资料:
  • 问题内容: -1作为转换为二进制的int表示为321。当我右移31次时,得到1(31个0和一个1)。但是当我右移32次时,我又得到-1。它不应该等于0吗? 问题答案: Java规范对移位运算符的解释如下: 如果左侧操作数的提升类型为,则仅将右侧操作数的最低5位用作移位距离。就像右手操作数受到掩码值的按位逻辑AND运算符(第15.22.1节)一样。因此,实际使用的移动距离始终在0到31(含)范围内。

  • 问题内容: 我想知道这是否是JVM错误? Java版本“ 1.6.0_0” OpenJDK运行时环境(IcedTea6 1.4.1)(6b14-1.4.1-0ubuntu13)OpenJDK 64位服务器VM(内部版本14.0-b08,混合模式) 当我运行它时会产生这个: 对于32的任意倍数,我也得到相同的结果。 我需要编写自己的右移来检查吗? 问题答案: http://docs.oracle.c

  • 问题内容: 即使int的最大值是2 31 -1,为什么Java HashMap的最大容量是1 << 30而不是1 << 31 ?最大容量初始化为 问题答案: Java使用带符号的整数,这意味着第一位用于存储数字的符号(正/负)。 一个四字节整数具有32位,其中数字部分由于有符号位而只能跨越31位。这将数字范围限制为 2 ^ 31-1 (由于包含0)到 -(2 ^ 31) 。

  • 问题内容: 运行下面的代码结果为0? 问题答案: 两个操作数(1和3)是整数,因此使用整数算术(此处为除法)。将结果变量声明为double只会导致除法后发生隐式转换。 当然,整数除法会返回除法四舍五入的真实结果。因此,0.333…此处的结果四舍五入为0。(请注意,处理器实际上不进行任何舍入,但是您仍然可以这样考虑。) 另外,请注意,如果两个操作数(数字)均以浮点数给出;3.0和1.0,甚至只是第一

  • 问题内容: 为什么有人在SQL子句中使用(通过连接字符串获得的两种SQL,无论哪种视图定义) 我在某个地方看到过,它将被用来防止SQL注入,但是看起来很奇怪。 如果进行注射,结果将与相同。 稍后编辑:视图定义中的用法如何? 谢谢您的回答。 仍然,我不明白为什么有人会使用这种构造来定义视图,还是在存储过程中使用它。 以这个为例: 问题答案: 如果条件列表在编译时未知,而是在运行时生成,则不必担心是否

  • 我们先看一下 RxSwift 能够帮助我们做些什么: Target Action 传统实现方法: button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside) func buttonTapped() { print("button Tapped") } 通过 Rx 来实现: button.rx.