每天进步一点点,坚持带来大改变!!!
前言:
接下来通过习题来介绍见识一下C语言位操作符的神奇妙用。
1.统计二进制中1的个数:
方法一:
思路:
假设统计15中1的个数:
1111
15%2==1
15/2==7;
111
7%2==1
7/2==3;
11
3%2==1
2/2==1;
1
1%2==1
1/2==0;
#include<stdio.h> //unsigned :将负数按照无符号数处理 int count_num_of_1(unsigned int num) { int count = 0;//统计1的个数 while (num) { if (num % 2 == 1) { count++; } num = num / 2;//去掉一位 } return count; } int main() { int num = 0; scanf("%d", &num); int n = count_num_of_1(num); printf("%d\n", n); return 0; }
方法二:
思路:
将一个数的二进制位向右移动32次,每次移动之后与1进行按位与,如果按位与的值等于1,计数器加加。按位与的特点是:如果两个都为1,则为1。
#include<stdio.h> int count_num_of_1(num) { int count = 0; int i = 0; for (i = 0; i < 32; i++) { if (((num >> i) & 1) == 1)//向右移动i位,按位与1. { count++;//计数器++ } } return count; } int main() { int num = 0; scanf("%d", &num); int n = count_num_of_1(num); printf("%d\n", n); return 0; }
方法三:
思路:
假设统计15中1的个数:
15二进制位:1111
1111 num
1110 num-1;
num&(num-1)
1110 num
1101 num-1;
num&(num-1)
1100 num
1010 num-1
num&(num-1)
1000 num
0100 num-1;
num&(num-1)
0000
循环多少次就说明有多少个1。
特点:每次按位与之后将最右边的1去掉。
#include<stdio.h> int count_num_of_1(int num) { int count = 0; while (num) { num = num & (num - 1); count++; } return count; } int main() { int num = 0; scanf("%d", &num); int n = count_num_of_1(num); printf("%d\n", n); return 0; }
2.统计两个整数中二进制位不同的个数:
方法一:
思路:两个整数的二进位向右移动1位然后按位与1,循环32次,如果不相等,然后count++;
#include<stdio.h> int count_diff_bit(int m, int n) { int count = 0; int i = 0; for (i = 0; i < 32; i++) { if (((m >> i) & 1) != ((n >> i) & 1)) { count++; } } return count; } int main() { int m = 0; int n = 0; scanf("%d%d", &m, &n);//从键盘录入两个数 int ret = count_diff_bit(m, n); printf("%d\n", ret); return 0; }
方法二:
思路:先进行两个数的异或操作,得到的二进制序列中有多少个一就说明有多少个不同的比特位,统计1的个数用n&(n-1)。
#include<stdio.h> int count_diff_bit(int m, int n) { int count = 0; //异或:相同则为0,相异则为1 int ret = m ^ n; while (ret) { ret = ret & (ret - 1); count++;//统计1的个数 } return count; } int main() { int m = 0; int n = 0; scanf("%d%d", &m, &n);//从键盘录入两个数 int ret = count_diff_bit(m, n); printf("%d\n", ret); return 0; }
3.获取一个二进制数的所有位,分别打印奇数位和偶数位
思路:
奇数位:一个整型的数有32个bit位,将第31个数向右移动30位然后按位与1进行打印。
其它位一次循环进行
偶数位:将第32个数向右移动31位然后按位与1进行打印。
#include<stdio.h> int main() { int n = 0; scanf("%d", &n); int i = 0; //获取奇数位: for (i = 30; i >= 0; i -= 2) { printf("%d ", (n >> i) & 1); } printf("\n"); //获取偶数位 for (i = 31; i >= 1; i -= 2) { printf("%d ", (n >> i) & 1); } return 0; }