首先,位运算是针对二进制的,(数字本来int,4字节,下面假设为1字节)。比如数字12,它的二进制本来是:
0000 0000 0000 0000 0000 0000 0000 1100
因为前面的数字大都是0,所以为了简写,我们保留1字节。在下文中我们12就写成:
0000 1100
int main() { int a = 0x10;//十六进制 int b = 20;//十进制 int c = 020;//八进制 printf("%d,%d,%d\n", a, b, c);//16,20,16 printf("%x\n", a);//%x:输出十六进制数字 printf("%x\n", 20);//14, printf("%c,%d,%x\n", 65, 65, 65);//'A',65,41 printf("%x,%X\n", 20000, 20000);//4e20,4E20 //练习 //0x124->转二进制->转八进制->转十进制 //0x124->0001 0010 0100 -> 444->292 return 0; }
int main() { int a = 20; int b = 024;//0开头的数据表示八进制数字 int c = 0x14;//0x开头的数据表示十六进制 int d = 0b10100;//0b开头的数据表示二进制 (新标准增加的) printf("%d,%d,%d,%d\n",a,b,c,d); return 0; }
我们以数字12,13举例,
具体运算如下:下面的运算都是针对二进制
- 去掉最后一位 | (101101->10110) | x >> 1
- 在最后加一个0 | (101101->1011010) | x << 1
- 在最后加一个1 | (101101->1011011) | (x << 1) | 1
- 把最后一位变成1 | (101100->101101) | x | 1
- 把最后一位变成0 | (101101->101100) | (x >> 1) << 1 x & ~1
- 最后一位取反 | (101101->101100) | x ^ 1
- 把右数第k位变成1 | (101001->101101, k = 3) | x | (1 << (k - 1))
- 把右数第k位变成0 | (101101->101001, k = 3) | x & 111011->x & ~(1 << (k - 1))
- 右数第k位取反 | (101001->101101, k = 3) | x ^ 100->x ^ (1 << (k - 1))
- 1.确定符号 2.确定数字 3.构造数字
- 得到1 | 1 (这一位是1)
- 得到0 & 0(这一位是0)
- 取反 ^ 1
- 取最右边的1位 | (1101101->1) | x & 1, x % 2
- 取末三位 | (1101101->101) | x & 111->x & ((1 << 3) - 1), x & 7
- 取末k位 | (1101101->1101, k = 4) | x & ((1 << k) - 1)
- 取右数第k位 | (1101101->1, k = 4) | (x >> (k - 1)) & 1
所有的数字成对,只有一个数字只出现一次,找到它
//1^3^5^3^1=1^1^3^3^5=5 //找打单的数字 int SingleNum(int* arr, int len)//O(n) { int tmp = 0; for (int i = 0; i < len; i++) tmp ^= arr[i]; return tmp; } int main() { int arr[] = { 1,5,3,7,9,6,1,3,9,6,5 };//所有的数字成对,只有一个数字只出现一次,找 //到它 //算法1:1.排序;2.遍历 O(nlogn) //算法2:从头到尾按位异或(按位异或相同的数字为0,5^5==0) int n = SingleNum(arr, sizeof(arr) / sizeof(arr[0])); printf("%d\n", n); return 0; }
统计一个数字二进制1的个数.例如9转为二进制是0000 1001,那么二进制中1的个数为2.
//统计十进制数字中1的个数例如1231212->3 得个位n%10 ,丢个位n/=10 //统计二进制中1的个数 int Bits(unsigned int n)//-1 ->11111111111111111111111111111111 { int count = 0;//计数器 while (n != 0) { if (n % 2 == 1) count++; n /= 2; } return count; } int main() { printf("%d\n", Bits(12345678)); printf("%d\n", Bits(0x12345678));//1+1+2+1+2+2+3+1 printf("%d\n", Bits(-1));//32 return 0; }
int Bits2(unsigned int n) {//n&1:得到二进制右数第1位; n>>=1:丢弃右数第1位 int count = 0; while (n != 0)//0x10000000 { count += n & 1; n >>= 1; } return count; } int main() { printf("%d\n", Bits(12345678)); printf("%d\n", Bits(0x12345678));//1+1+2+1+2+2+3+1 printf("%d\n", Bits(-1));//32 return 0; }
int Bits(unsigned int n) { int count = 0; while (n != 0) { count++; n &= n - 1; //丢弃二进制最右边的1 } return count; } int main() { printf("%d\n", Bits(12345678)); printf("%d\n", Bits(0x12345678));//1+1+2+1+2+2+3+1 printf("%d\n", Bits(-1));//32 return 0; }
int func(unsigned i) //统计二进制1的个数 { unsigned temp = i; temp = (temp & 0x55555555) + ((temp & 0xaaaaaaaa) >> 1); temp = (temp & 0x33333333) + ((temp & 0xcccccccc) >> 2); temp = (temp & 0x0f0f0f0f) + ((temp & 0xf0f0f0f0) >> 4); temp = (temp & 0xff00ff) + ((temp & 0xff00ff00) >> 8); temp = (temp & 0xffff) + ((temp & 0xffff0000) >> 16); return temp; } int main() { printf("%d\n", func(0x7f530829));//3+4+2+2+1+1+2=15 return 0; }
变1: x | (其它位是0,当前位是1)
变0 : x&(其它位是1,当前位是0)
取反:x ^ (其它位是0,当前位是1)