我应该在Java中按位移2除以?

Mat*_*ins 28 java performance bit-manipulation bit-shift division

可能重复:
比Java中的乘法和除法更快地移位位?.净?
快速Java优化问题

很多年前,在大学里,我学会了正确地按位移动实现与除以2相同的操作,但通常要快得多.自从9-10年前我了解到这一点以来,我不确定Java在这方面是如何出现的.Java编译器是否自动将二分频转换为位移操作,还是应该自己在代码中手动执行位移操作?

Pau*_*sik 61

除非你在一个商店和代码库中工作,其中比特移位是常见的,恕我直言,你冒着混淆的风险.是的,表达式可能在逻辑上等效,但是:

  • n00b可能会被替代语法混淆
  • 像大学一样,自从大学以来没有做过任何改变的老家伙可能会感到困惑
  • 如果你有点转变并觉得有必要评论你刚刚做了什么,那么你肯定是关闭的.简单的划分是自我记录,任何熟悉基础数学的人都会清楚
  • 你不会超越编译器来优化那些简单的事情,所以不要费心去尝试
  • 作为良好的编码实践,最好使你的代码简单/香草而不是聪明(呃)

所有这些都是相对的,而且,真的取决于您的商店标准.如果你的同事喜欢按位移动,那么无论如何都会出现并且按位移动.

  • 它在旁观者的眼中.为什么`x*2`比`x << 1`更少混淆?是不是`x << 1`明显意味着`x*2`?这就像说'x + 1'比"1 + x"更清晰. (30认同)
  • 以另一种方式来表达@PaulSasik的陈述,这是一个抽象问题.是的,数字在内部用二进制表示,但是当程序员有一个数字`x`并想要将它除以恰好是'2'的数字时(因为我们喜欢这半事),程序员就在十进制数的抽象层.在这一层中移位是乘以"10".将`x >> 1`视为`x/2`是将抽象层下移到二进制表示.当程序员已经在二进制抽象层中处理二进制数时,位移使"有意义". (17认同)
  • 许多程序员,特别是初级开发人员,不熟悉位移,或者不会立即识别意图.对于程序员来说,这基本上是一个可用性参数,可以在你之后处理代码. (9认同)
  • @Pacerier:`x << 1`相当于`x*2`只对程序员来说是清楚的,他们需要或想要在某种程度上喋喋不休.自从我大学二年级以来,我没有必要对任何东西进行任何改变,并且在代码中用位移代替简单的除法或乘法符号只会引发WTF? (6认同)
  • @ Chris2048:如果你需要注释代码,因为你选择的运算符最初可能会混淆另一个程序员,那么,IMO,你刚刚让代码更难以理解. (5认同)

Rém*_*émi 19

现代编译器非常聪明,能够为两个分区生成最快的代码.如果速度更快,他们会做出改变.如果你想要实现的是除以2,使用除法将使你的代码更清晰.当要分割的数字为负数时,您将避免出现问题.


Mic*_*rdt 15

是的,这是任何试图进行编译器优化的人都会做的第一件事(并且已经完成了至少50年),它肯定是由Java JIT编译器完成的,你可能很难找到它任何不这样做的编译器.

即使他们没有,仍然应该避免过早的微优化,以使代码更清晰.

  • 这应该是答案,而不是实际回答 java 是否这样做的问题,人们在其良好实践与否之间跳舞...... (3认同)

Mal*_*ist 11

CPU的除法例程将处理此问题.你没有必要这样做.

这被称为过早优化.

  • 早期优化!=过早优化.是*大多数时候,有人想开始讨论它可能是过早优化的一个例子,但情况并非总是如此.我个人已经看到了一些实例,我得到了明显更好的结果,因为我有编译器没有的信息.我讨厌每个人总是开始大喊"过早优化!!!" 任何时候这样的事情都会提出来. (18认同)
  • 移位将是几乎所有架构上的单周期指令,而最佳CPU每周期只能执行2位除法(最新的英特尔核心RADIX-16分频器).对于32位,在最佳情况下,对于一个除法,使得1个周期用于移位而对于16个周期.添加启动成本和管道停顿,最终得到的因素大约为20. (5认同)
  • CPU的除法"例程"实际上是一条指令,它总是比位移慢20倍左右."编译器"可以用移位替换除法,但就是这样. (4认同)
  • 好的,这是晚了3年,但是分区与位移的简单时间比较显示,在10亿次计算时,位移速度快〜5倍.不知道你需要多少计算来达到x20标记,但我猜你仍然会等待它完成:) (3认同)