使用移位运算符计算一个数的2的次幂的倍数。
n << 1 即等价于 n*2
n >> 1 即等价于 n/2
原理可参考十进制:
n << 1 相当于结尾加个0,等价于 n*10。
n >> 1 相当于结尾去掉一位,等价于 n/10。
注:对于右移,各二进位全部右移若干位,对无符号数,高位补0,有符号数,各编译器处理方法不一样,有的补符号位(算术右移),有的补0(逻辑右移)
使用&运算符判断奇偶
printf( n&1 ? "奇数" : "偶数");
不使用临时变量交换两数
异或运算符定义:
两个位相同为0,相异为1。
性质:
1.满足交换律:b^(a^b)=b^b^a
2.一个数和自己异或的结果为0
3.任何数与0异或都不变
利用这三条性质可以证明swap函数的正确性。
void Swap(int &a, int &b)
{
if (a != b)
{
1.a = a ^ b;
2.b = b ^ a;
3.a = a ^ b;
}
}
第二条语句先给b赋a的值:
b = b^(a) = b^(a^b) = b^b^a = a;
第三条语句再给a赋b的值
a = (a)^(b) = (a^b)^a = a^a^b = b;
求绝对值
int my_abs(int a)
{
int i = a >> 31;//取符号位
return i == 0 ? a : (~a + 1);//若为正数,直接返回,否则取反+1
}
利用异或的第三条性质:
3.任何数与0异或都不变
上述代码可优化成秀操作最终版:
int my_abs(int a)
{
int i = a >> 31;
return ((a ^ i) - i);
}
防溢出式求两数的平均值
求平均值一般会想到(x+y)/2 ,但x+y可能会溢出,所以用位运算能防止溢出。
int avg=(x&y) +((x^y)>>1);
首先对上式各部分做个解释:
x&y 取出x和y二进制都为‘1’的所有位
x^y x和y中有一个为‘1’的所有位
(x^y)>>1 除以2
思想就是:
就是把x+y的和分成两部分,
一部分是x和y都为‘1’的部分,因为求平均数要相加后除以2,所以把这两个1当作一个1和后面的直接加就行了 。
另一部分是x为‘1’,y为‘0’的部分,以及y为’1‘,x为’0‘的部分,两部分加起来除以2.
然后这两部分的平均值相加就可以了