以下哪一种技术是整数除2的最佳选择,为什么?

技巧1:

x = x >> 1;

技巧2:

x = x / 2;

这里x是整数。


当前回答

x / 2更清晰,x >> 1快不了多少(根据一个微基准测试,对于Java JVM快30%左右)。正如其他人所注意到的,对于负数,舍入略有不同,所以当您想处理负数时必须考虑这一点。一些编译器可能会自动将x / 2转换为x >> 1,如果他们知道这个数字不可能是负数(即使我无法验证这一点)。

即使x / 2可能不使用(慢)除法CPU指令,因为一些捷径是可能的,但它仍然比x >> 1慢。

(This is a C / C++ question, other programming languages have more operators. For Java there is also the unsigned right shift, x >>> 1, which is again different. It allows to correctly calculate the mean (average) value of two values, so that (a + b) >>> 1 will return the mean value even for very large values of a and b. This is required for example for binary search if the array indices can get very large. There was a bug in many versions of binary search, because they used (a + b) / 2 to calculate the average. This doesn't work correctly. The correct solution is to use (a + b) >>> 1 instead.)

其他回答

显然,如果你是在为下一个阅读你的代码的人写代码,那么你应该追求“x/2”的清晰度。

然而,如果速度是你的目标,那就两种方法都试一试,把握好时间。几个月前,我做了一个位图卷积例程,它涉及到在一个整数数组中步进,并将每个元素除以2。我做了各种各样的事情来优化它,包括用“x>>1”代替“x/2”的老技巧。

当我计算这两种方式时,我惊奇地发现x/2比x>>1快

这是使用Microsoft VS2008 c++并打开默认优化。

我说这些是为了参加编程比赛。一般来说,他们有非常大的输入,除以2会发生很多次,已知输入是正的或负的。

X >>1比X /2好。我在ideone.com上运行了一个程序,其中发生了超过10^10除以2的运算。X /2花了将近5.5s,而X >>1花了将近2.6s。

使用除法(/),假设这样更清楚。编译器将相应地进行优化。

这个问题的答案取决于你工作的环境。

If you're working on an 8-bit microcontroller or anything without hardware support for multiplication, bit shifting is expected and commonplace, and while the compiler will almost certainly turn x /= 2 into x >>= 1, the presence of a division symbol will raise more eyebrows in that environment than using a shift to effect a division. If you're working in a performance-critical environment or section of code, or your code could be compiled with compiler optimization off, x >>= 1 with a comment explaining its reasoning is probably best just for clarity of purpose. If you're not under one of the above conditions, make your code more readable by simply using x /= 2. Better to save the next programmer who happens to look at your code the 10 second double-take on your shift operation than to needlessly prove you knew the shift was more efficient sans compiler optimization.

所有这些假设都是无符号整数。简单的移位可能不是你想要的符号。此外,DanielH提出了一个关于在ActionScript等特定语言中使用x *= 0.5的好观点。

Knuth说:

过早的优化是万恶之源。

所以我建议用x /= 2;

这样代码很容易理解,而且我认为这种形式的操作优化,对处理器来说不会有太大的区别。