【问题标题】:To divide by 2 which one is better Right Shift Operator or traditional division operator? [duplicate]除以 2 哪个更好右移运算符或传统除法运算符? [复制]
【发布时间】:2014-05-08 06:15:13
【问题描述】:

在阅读Collections.reverse方法的Java源代码时,Right Shift operator is used for finding middle.

......
            for (int i=0, mid=size>>1, j=size-1; i<mid; i++, j--) // Right Shift 
                swap(list, i, j);
.....

使用传统的除以 2 方法也可以做到这一点。

我在堆栈Right Shift to perform division 上进行了探索,发现使用除法运算符而不是右移更好。

更新But then why java guys used Right Shift and not division ?

So which approach is better to use and Why ?

【问题讨论】:

  • I explored on stack Right Shift to perform division and find that its better to use division operator and not Right Shift.... 呃你好?
  • 所以您在发布此内容之前已经找到了副本?不相信现有的答案不是提出重复问题的理由。是什么让您认为这个问题实例的答案会比上次更可信?
  • 我已经提到了那个链接。所以显然我在问一些没有回答的问题。
  • 那你最好澄清一下你对你的问题有什么新感觉,否则它会很快被关闭并可能被删除。
  • 我在更新中提到过

标签: java bitwise-operators


【解决方案1】:

有符号除以 2 和右移 1 并不完全等价。除以 2 轮到零,即使是负数也是如此。向下右移 1 轮,这意味着 -1 &gt;&gt; 1-1(而 -1 / 2 为零)。

具体来说,这意味着如果 JIT 编译器不能(或不能)证明一个数字不能是负数(如果你发布了完整的代码,我可能已经能够检查),它必须这样做一个比右移更复杂的东西 - 像这样:(将eax 除以 2 和 clobbers edi,基于 GCC 输出)

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

如果你使用了 1 的右移,它会是这样的

sar eax, 1

这不是差异,但它差异,所以“它没有任何区别” - 人群现在可以回家了。好的,它只是循环初始化,所以它不会对性能产生严重影响,但我们不要忘记这是库代码 - 适用不同的指导方针。具体来说,可读性较少被强调,而“除非绝对必须,否则不要浪费性能”的指导方针更加强调。在这种情况下,没有充分的理由在那里写size / 2,只会让性能稍微差一点。没有任何好处。

此外,在这种情况下,我发现这种可读性有点愚蠢。如果有人真的不知道 size &gt;&gt; 1 做了什么,那是 他们的 问题 - 它只是基本运算符之一,甚至不是一些复杂的运算符组合,如果你看不懂,那么你就不要不懂Java。

但请随意在您自己的代码中使用size / 2。从这个答案中得出的结论不应该是“除以 2 不好”,而是“库代码不应该为了可读性而牺牲性能”。

【讨论】:

  • +1 表示反对所谓的“可读性”,在这种情况下,这意味着“我对 int 的位、字节、单词和 2 的补码表示一无所知,所以我不明白代码。”
【解决方案2】:

除非迫切需要速度,否则最好使用可读性更强的选项。

使用清晰、明显的划分,然后如果您发现自己需要稍后进行优化,您可以更改为正确的班次并明确注释。

【讨论】:

  • +1:我强烈怀疑 shift 是否明显更快。对于 JVM 来说,这似乎是一个很容易执行的优化,所以如果转移速度更快,它可能会自动优化。
  • 这不是一个简单的优化,JIT 必须证明除数不是负数。请参阅@harold 的回答。
【解决方案3】:

实际上,这并不重要,但除法使意图更清晰,我只能想象出于“性能原因”而尝试进行位移。但现在是 2014 年,您还没有手动编写 x86 程序集,因此尝试像这样优化代码是浪费时间。

【讨论】:

  • 被从未手写过汇编的人投反对票。
  • 我自己总是用橡皮泥雕刻我的机器代码的零和一。
  • 好吧,你不能打败自制的小菜。
【解决方案4】:

与除法运算符相比,右移运算符速度更快。 如您所知,所有数据都以二进制格式存储和处理。右移直接作用于二进制格式,因此快速且最优。除法适用于整数,因此速度很慢且不是最优的。 但是由于现在的处理器速度相当好,而且你使用哪个运算符并没有真正的不同,所以选择真的是你的。 如果您认为您的应用程序已经占用了过多的处理器速度,并且您确实需要减轻负载,则可以使用右移。对于轻量级应用,除法运算符是合适的。

【讨论】:

  • fast:怎么样?给我们一些证据。
  • 存储一些数据时,先将其转换成二进制格式再存储。当您再次检索要更改的数据时,二进制形式将转换为所需的形式,然后应用更改。对于右移,不需要从二进制格式进行第二次更改,因此速度很快,因为它减轻了处理器负载。
  • 这两个操作都由一个独立的唯一指令(iushriadd)在字节码级别进行检测。除非你真的知道字节码是如何实现的,否则你将很难证明这个答案。
  • 请阅读这篇文章。 community.oracle.com/message/8717135
猜你喜欢
  • 2011-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-30
  • 1970-01-01
  • 2011-07-22
  • 1970-01-01
相关资源
最近更新 更多