C++位运算
总结一下C++中位运算的用法。
&(与运算)
举例 11&3 = 3
00001011
& 00000011
= 00000011
= 3
常用例子
我们判断是否被2整除,一般写成if(n%2==0),使用位运算符也可写作if(n&1==0)
|(或运算)
举例 11|3 = 11
00001011
| 00000011
= 00001011
= 11
<<(向左位移)
<<向左移动n位,右边自动补0.
举例 11<<1=22
00001011 << 1
00010110 = 22
m*2^n = m<
>>(向右位移)
>>向右位移,左边自动补0.
举例 11>>1=5
00001011 >> 1
00000101 = 5
同理m/2^n = m>>n(m除以2的n次方相当于m右移n位)
^(异或运算符)
两个相同的位变成0,不同的位变成1
举例 11^3=8
00001011
^ 00000011
= 00001000
= 8
应用1: Given an array of integers, every element appearstwice except for one. Find that single one.
比如int i = {1,2,3,3,2,1,5},找去其中的5
解法:将数组i中的所有数字依次异或,最后剩下的就是只出现了一次的数字。
应用2:不借助临时变量,交换两个变量的值
void swap(int &a,int &b)
{
a ^= b;
b ^= a;
a ^= b;
}
分析一下
例如a=8,b=4
a=1000 b=0100
a=a^b a=1100(表示了a和b差异位)
b=b^a b=1000(用差异位与b异或还原了a,此时b就是a的原始值)
a=a^b a=0100(用差异位与a,也就是现在的b异或还原了b,此时a就是b的原始值)
~(按位取反)
加法中的应用
**x-y=x+~y+1
~y=-y-1**
例如~11=-11-1=-12
求解二进制中1的个数
题目描述:输入一个整数,求解二进制中1的个数,负数用补码来表示。
解法:
1. 普通法:按位与1进行与运算,然后右移直到数字变成0,来求解1的个数。
2. 快速法:使用n&(n-1),不断清除n最右边的1,直到n为0,与的次数就是1的个数。(为什么n &= (n – 1)能清除最右边的1呢?因为从二进制的角度讲,n相当于在n - 1的最低位加上1。举个例子,8(1000)= 7(0111)+ 1(0001),所以8 & 7 = (1000)&(0111)= 0(0000),清除了8最右边的1(其实就是最高位的1,因为8的二进制中只有一个1)。再比如7(0111)= 6(0110)+ 1(0001),所以7 & 6 = (0111)&(0110)= 6(0110),清除了7的二进制表示中最右边的1(也就是最低位的1)。)
代码如下:
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
/*int NumberOf1(int n) { //快速法
int result = 0;
while(n) {
n = n & (n-1);
result++;
}
return result;
}*/
int NumberOf1(int n) { //普通法
int result = 0;
int BitNum = sizeof(n)*8;
for(int i=0;i<BitNum;++i) {
if(n & 1)
result++;
n >>= 1;
}
return result;
}
int main() {
cout<<NumberOf1(-8)<<endl;
return 0;
}