按位与&、右移>>
按位与&的基本概念:a&b时,只有同时为1结果才为1,即0&1=0,1&0=0;0&0=0;1&1=1
右移>>的基本概念:右移一个比特位,左边补0右边舍弃
题目:统计二进制中1的个数,利用该题分析按位与&、右移>>的应用
典型的错误代码:
#include<stdio.h>
int main()
{
int num = 0;
int count = 0;
scanf("%d", &num);
while (num)
{
if (num % 2 == 1)
{
count++;
}
num = num / 2;
}
printf("%d\n", count);
return 0;
}
但是上述代码无法满足负数的情况,比如-1
原码:10000000 00000000 00000000 000000001
反码:11111111 11111111 11111111 11111110
补码:11111111 11111111 11111111 11111111
如果按照上述代码,输入num=-1,-1%2==0,-1/2==0,输出的count实际上是0
所以显然上述代码时错误的
正确的代码:
#include<stdio.h>
int main()
{
int num = 0;
int i = 0;
int count = 0;
scanf("%d", &num);
for (i = 0; i < 32; i++)
{
if (((num >> i) & 1) == 1)
{
count++;
}
}
printf("%d\n", count);
return 0;
}
上述代码是基于位操作符&(按位与只有两个数都是1结果才为1)来考虑的,我们将32位都拿去与1比较,即可得出二进制中1的个数。
但是上述代码并不是最优解,最经典的代码其实是下述代码:
#include<stdio.h>
int main()
{
int num = 0;
int count = 0;
scanf("%d", &num);
while(num)
{
num = num&(num - 1);
count++;
}
printf("%d\n", count);
return 0;
}
num&(num-1)实际上是消除一个1,我们统计总共消除了多少次即可。
上述思路还可以用来写:求两个数二进制不同位的个数
可以自己尝试
异或^
异或^的基本概念:不同为1,相同为0 即0^1=1 1^0=1 0^0=0 1^1=0
题目:不创建变量的情况下交换两个数的值,以该题分析异或^的实际运用
#include<stdio.h>
int main()
{
int m = 0;
int n = 0;
scanf("%d%d", &m, &n);
m = m^n;
n = m^n; // 此时m=m^n 所以实际上n=m^n^n 其中n^n为0然后m^0为m,把m的值给了n
m = n^m; // 此时m=m^n n=m 所以实际上是m=m^m^n 其中m^m为0然后0^n为n,把n的值给了m
printf("m=%d n=%d", m, n);
return 0;
}
按位或|
按位或|的基本概念:两个数只要有一个为1就为1,即 1|1=1, 1|0=1,0|1=1 ,0|0=0
举例:11 | 10 为多少 (这两个是数值为十进制)
11的二进制表示为:1011
10的二进制表示为:1010
所以11 | 10二进制表示为:1011 即结果为11