为什么JDK使用移位而不是乘法/除法?

时间:2012-02-12 09:36:58

标签: java optimization collections bit-manipulation priority-queue

我有以下问题:

如果被问及是否使用移位与乘法或除法(例如答案),请让JVM进行优化。

此处示例:is-shifting-bits-faster-than-multiplying

现在我正在查看jdk源代码,例如Priority Queue,代码仅使用乘法和除法(有符号和无符号)进行移位。

理所当然地认为SO中的帖子是有效的答案我想知道为什么在jdk他们更喜欢通过转移来做到这一点?

这是一些与性能无关的微妙细节吗?我怀疑它必须与上/下溢乘法和除法有关但我不确定。

有人有想法吗?使用移位是否能更好地处理溢出问题?或者只是品味问题?

4 个答案:

答案 0 :(得分:6)

我认为他们在这个具体的例子中使用符号位。 Java缺少无符号类型,因此对于使用最高有效位的数字,无法使用a >>> 1模拟a /= 2。请注意代码在整个示例中仅使用>>>。我有理由相信这是为了充分利用整个比特范围。

答案 1 :(得分:5)

除了大多数系统上的转换速度快于分割。 >>>执行无符号运算,而除法运算则不执行。例如如果你想要两个值的中点,你需要使用>>>来避免溢出。 (有关类似代码,请参阅Arrays.binarySearch)

答案 2 :(得分:3)

偏好在Java中转移的一些正当理由:

  • 如果您有可能在非优化环境中运行,并且无法保证JIT编译器将为您进行必要的优化。现在这种情况可能很少见,但在某些情况下仍可能发生。
  • 如果你真的做位操作而不是数字操作 - 在源代码中更清楚直接使用移位
  • 如果您想要无符号操作(例如,您可以轻松执行无符号移位,但不能执行无符号除法)

答案 3 :(得分:2)

更多的是品味问题。有些人习惯于二元操作,他们更习惯于他们(我个人也在我自己编写的代码中使用)。但是从性能的角度来看,两者的行为相同(优化发生在编译时,因此使用shift会改善编译时间,但只需要很小的一部分就可以忽略它。)

编辑因为经常发生的事情,我从我给出的每个答案中都学到了新的东西:考虑this。它证明了为什么除以2不能总是优化转换。所以我的上述评论几乎完全错误,只要java没有无符号类型。