使用与按2除以找到数组中值的按位运算是否有优势?

时间:2014-05-24 05:15:08

标签: java arrays bit-manipulation

例如:

除以2

int med = lo + (hi - lo) / 2;

按位右移

int med = lo + hi >>> 1;

我想知道,使用按位运算而不是除以2有什么特别的优势吗?使用按位运算是否可以提供更有效或更可靠的计算?

我很想知道因为java.util.Arrays在执行二进制搜索时使用了按位移位。

3 个答案:

答案 0 :(得分:4)

不太可能

您的编译器中有一个优化器,它知道如何以目标处理器架构的速度倍增。所以编译器可能已经进行了这种优化。

通常可以将乘法或除法分解为一系列移位和加法,并且如果该系列操作将比乘法或除法更快,则编译器将使用它。

答案 1 :(得分:3)

如果您恰好使用2的幂,则左右移位明显比大多数(所有?)CPU上的乘法和除法运算快。但是,它会降低某些读取器和某些算法的代码清晰度。

关于这篇文章的更多信息:

Is shifting bits faster than multiplying and dividing in Java? .NET?

答案 2 :(得分:1)

没有编译器会如此愚蠢,以至于实际发出完全除法。但这并不意味着没有区别。一个2分的签名除法比右移更复杂,你必须做这样的事情:

mov edi, eax
shr eax, 31
add eax, edi
sar eax, 1

除非您能证明您除以2的数字是非负数。这需要证明hi >= lo。在二分搜索中,这可能是可行的(如果在计算中间之前有if (hi < lo) return false;或类似的东西)。

即使这样,分割方式仍然有3个操作,而换档版本则有2个。也许一个足够聪明的JIT编译器也可以看到它,但我们现在要求它越来越多。

Java开头几天的旧解释器当然不会做任何这样的事情,第一批JIT编译器也不会这样做。

因此编写hi + lo >>> 1有一个小优势,并且确实没有缺点。那么为什么不会他们使用它?