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;
}