问题描述
在读取 Collections.reverse
方法的Java源代码时,右移运算符用于查找中间值.
While reading Java Source code for Collections.reverse
method, 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分法来完成.
Same can be done by using traditional divide by 2 approach.
我在堆栈右移执行除法运算中,发现最好使用除法运算符而不是Right Shift.
I explored on stack Right Shift to perform division and find that its better to use division operator and not Right Shift.
更新:但是为什么Java家伙使用Right Shift而不是除法?
那么哪种方法更好用?为什么?
So which approach is better to use and Why ?
推荐答案
有符号除以2和右移为1并不完全等效.除以2,除数会朝着零舍入,即使是负数也是如此.右移1向下向下舍入,这意味着 -1>>1
为 -1
(而 -1/2
为零).
Signed division by 2 and right shift by 1 are not completely equivalent. Division by 2 rounds towards zero, even for negative numbers. Right shift by 1 rounds downwards, which means -1 >> 1
is -1
(whereas -1 / 2
is zero).
具体而言,这意味着,如果JIT编译器无法(或无法)证明数字不能为负数(如果您已发布完整代码,则我可能能够进行检查),则必须这样做不仅是右移,还需要一些复杂的操作-像这样:(根据GCC的输出结果,将 eax
除以2,将整洁的 edi
除以数字)
Concretely, that means that if the JIT compiler can not (or does not) prove that a number can not be negative (if you had posted the full code, I might have been able to check that), it has to do a something more complicated than merely a right shift - something like this: (divides eax
by 2 and clobbers edi
, based on what GCC output)
mov edi, eax
shr eax, 31
add eax, edi
sar eax, 1
如果您使用了右移1,那就像是
If you had used a right shift by 1, it would just be something like
sar eax, 1
这不是大区别,但是 是区别,因此它没有任何区别"的人群现在可以回家了.好的,它仅在循环初始化上进行,因此不会对性能产生严重影响,但是请不要忘记这是库代码-适用不同的准则.具体来说,不那么强调可读性,而更加强调除非绝对必要,否则不要浪费性能"的准则.在这种情况下,没有充分的理由在此处编写 size/2
,所有要做的就是使性能稍差一些.没有上行空间.
It's not a big difference, but it is a difference, so the "it doesn't make any difference"-crowd can go home now. Ok it's only on the loop initialization, so it doesn't have a serious impact on performance, but let's not forget that this is library code - different guidelines apply. Specifically, readability is less emphasized, and the guideline "don't waste performance unless you absolutely must" is more emphasized. Under the circumstances, there is no good reason to write size / 2
there, all that would do is make the performance a tiny bit worse. There is no upside.
此外,在这种情况下,我发现这种可读性有点愚蠢.如果某人真的不知道 size>>1
确实是问题,这是他们的问题-它只是基本的运算符之一,甚至不是一些复杂的运算符组合,如果您看不懂它,那么您就不懂Java.
Also, I find this readability thing a little silly in this case. If someone really doesn't know what size >> 1
does, that's their problem - it's just one of the basic operators, not even some convoluted combination of operators, if you can't read it then you don't know Java.
但是请随时在自己的代码中使用 size/2
.从这个答案中得出的结论不应该是除以2是不好的",而应该是"库代码不应为了提高可读性而牺牲性能".
But feel free to use size / 2
in your own code. The takeaway from this answer shouldn't be "division by 2 is bad", but rather, "library code shouldn't sacrifice performance for readability".
这篇关于用2除以哪个更好?右移运算符或传统除法运算符?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!