版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/FlushHip/article/details/82495034
首先要说明,这里讨论的区别无关性能方面。
看一下下面这个代码,然后判断两个结果是一样的吗
#include <bits/stdc++.h>
using namespace std;
int main()
{
for (int n; EOF != scanf("%d", &n); ) {
printf(">> 1 : %d\n", n >> 1);
printf("/ 2 : %d\n", n / 2);
}
return 0;
}
下意识你会觉得肯定一样啊,但是你真的有输入任意整数试试看吗?
我挑了几个整数,结果如下:
-5 >> 1 : -3 / 2 : -2 -4 >> 1 : -2 / 2 : -2 -3 >> 1 : -2 / 2 : -1 -2 >> 1 : -1 / 2 : -1 -1 >> 1 : -1 / 2 : 0 0 >> 1 : 0 / 2 : 0 1 >> 1 : 0 / 2 : 0 2 >> 1 : 1 / 2 : 1 3 >> 1 : 1 / 2 : 1 4 >> 1 : 2 / 2 : 2 5 >> 1 : 2 / 2 : 2
总结一下:
n
为非负数时,>> 1
和/ 2
的结果是一样的n
为负数且还是偶数时,>> 1
和/ 2
的结果是一样的n
为负数且还是奇数时,>> 1
和/ 2
的结果是不一样的
原因是奇数除二会发生截断现象。而>> 1
和/ 2
在n
为负奇数时截断的反向不一样。
-5 / 2 = -(int)2.5 = -2
,这里是把绝对值变小了,加个负号,结果就变大了。-5 >> 1 = (1011) >> 1 = (1101) = -3
,假设用4-bit
表示一个整数,补码表示。发现结果变小了。
我们纵向比较一下
-5 / 2 = -2
,5 / 2 = 2
。这表明除二是向零取整-5 >> 1 = -3
,5 >> 1 = 2
。这表明右移一位是向下取整
所以我们之前说除二向下取整的说法不明确,应该说成非负数除二是向下取整,整数除二是向零取整。
有了这个之后,我们就发现二分取中点的次完美写法是mid = (l + r) >> 1
。详情见二分以及编程过程中求中点各种写法思想解析以及完美写法。