7

我有以下问题:为什么JDK使用移位而不是乘/除?

如果询问是否使用移位与乘法或除法,例如答案是,让JVM优化。

实施例这里:is-shifting-bits-faster-than-multiplying

现在我一直在寻找在JDK源,例如Priority Queue和代码仅使用移位了对乘法和除法(符号和无符号)。

理所当然地认为SO中的帖子是有效的答案,我想知道为什么在jdk中他们更喜欢通过转换来实现它?

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

任何人有想法?使用转移处理更巧妙的溢出问题?或者这只是一个品味问题?

回答

6

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

+0

所以不可能写无bug的代码没有移位运算符微妙像这样的问题? – Cratylus 2012-02-12 09:45:29

+0

@ user384706当然你可以:一个简单的三元操作符在这里和那里可以帮助你做到这一点。但是,效率会受到影响。 – dasblinkenlight 2012-02-12 09:49:41

+0

是否有可能展示一个这样的例子?我有兴趣了解 – Cratylus 2012-02-12 10:04:16

2

这更多的是品味的问题。有些人习惯于二进制操作,以至于他们更适合他们(我个人也在自己编写的代码中使用这种操作)。然而,从性能角度来看,两者的表现相同(优化发生在编译期,所以使用shift会提高编译时间,但只有很小的一部分,您可以忽略它)。

编辑而且正如我经常给出的答案中经常会有新的东西:考虑this。这证明了为什么两分之一不能总是优化转移。所以我上面的评论几乎是完全错误的,只要java没有无符号类型。

+1

更一般地说:如果Java能够保证数字是正数,那么Java中的JIT只能用移位2替换div。如果没有,我们需要一个更复杂的例程(基本上归结为3个班次和一个分支的免费版本,或分支和添加+班) – Voo 2012-02-12 13:09:04

3

一些正当的理由更喜欢在Java中移:

  • 如果有,您可以在非优化的环境运行一个机会,你不能保证JIT编译器将使为您进行必要的优化。现在这可能很少见,但在某些情况下仍然可能发生。
  • 如果你是真正做位操作而非数值运算 - 它是在源代码如果你想无符号运算(例如,你可以很容易地做到无符号转移到使用的变化直接
  • 更清楚,但没有无符号除法)
+0

我认为理由3是为什么例如在优先队列实施他们喜欢转移? – Cratylus 2012-02-12 09:59:17

5

除了在大多数系统上的转换速度比除法更快。 >>>执行未签名的操作,该划分没有。例如如果你想要两个值的中点,你需要使用>>>来避免溢出。 (请参阅Arrays.binarySearch获取类似代码)

+0

我想知道为什么你在第一句话中提到性能,不管JVM如何优化它呢?这是我从OP – Cratylus 2012-02-12 14:47:21

+1

中提到的其他SO线程所理解的,如果输入是负数, JVM不能总是证明输入是非负的,在这种情况下,它必须受到分裂的打击。 – 2012-02-12 15:36:01

+0

@LouisWasserman:所以你说我们必须总是使用移位操作符,因为JVM不会总是按照我们的预期进行优化?在我连接的SO线程中,没有提到这个,我相信 – Cratylus 2012-02-12 15:46:27

相关问题