文章目录
- 前言
- 一、n&(n-1)的运用场景(n为整数)
- [二、&1 和 >>的应用场景](#二、&1 和 >>的应用场景)
- 总结
前言
本篇文章介绍利用c语言的位操作符解决一些练习题,目的是掌握各个位操作符的使用和应用场景。
表1.1为c语言中的位操作符
操作符 | 含义 |
---|---|
& | 按位与 |
| | 按位或 |
^ | 按位异或 |
~ | 按位取反(包括符合位) |
<< | 左移 |
>> | 右移 |
表1.1 位操作符表
注意:
- 位操作符除"~"为单目操作符外,其余均为二目操作符,即有两个操作数
- 参加位操作符的对象只能是整型或字符型数据。
一、n&(n-1)的运用场景(n为整数)
题目:求一个整数存储在内存中的二进制位中1的个数(补码中1的个数)
n&(n-1)的过程如下(假设n = 15):
图1.1 n&(n-1)过程图 不断通过n&(n-1),每一次得到的结果是消去最右边的1;
原理:不断地向左借位,然后利用&操作符消去。 代码实现如下:
c
int count_2scomplement_3(int num)
{
int count = 0;
while (num)
{
count++;
num = num & (num - 1);
}
return count;
}
题目:判断一个数是不是2的n次方
这到题依然可以利用n&(n-1)进行解答,如果一个数是2的n次方,则意味只有一个1。如果n&(n-1)的结果为0,那么这个值就是2的n次方。
代码实现如下:
c
int main()
{
int num = 0;
scanf("%d", &num);
if (0 == (num & (num - 1)))
printf("%d is 2^n\n", num);
else
printf("%d is not 2^n\n",num);
return 0;
}
题目:两个int(32位)整数的m和n二进制表达式中,有多少个不同的位
这道题的思路是:m与n进行异或运算后,得到m和n的不同位,即1的个数就是不同位的个数,此时,这题又回到了统计1的个数,即第一题的解法。
代码实现如下:
c
int main()
{
int m = 0;
int n = 0;
int ret = 0;
scanf("%d %d", &m, &n);
int a = (m ^ n);
while(a)
{
ret++;
a = a&(a-1);
}
printf("%d", ret);
return 0;
}
二、&1 和 >>的应用场景
利用&1和>>可以统计一个二进中1或者0的个数;
利用&1和>>也可以获得任意一个位的值。
题目:求一个整数存储在内存中的二进制位中1的个数(补码中1的个数)
利用&1和>>进行解题,代码实现如下:
c
int count_2scomplement_2(int num)
{
int count = 0;
int rightmovetimes = 0;
for (rightmovetimes = 0; rightmovetimes < 32; rightmovetimes++)
{
if ((num >> rightmovetimes) & 1)
{
count++;
}
}
return count;
}
num >> rightmovetimes) & 1 == 1,则统计1的个数;为0则统计0的个数。
获取一个整数二进制序列中所有的奇数位和偶数位,分别打印二进制序列
要求:从高位开始打印
这道题的思路依然是利用&1和>>,从高位开始
代码实现如下:
c
int main()
{
int num = 0;
scanf("%d", &num);
int i = 0;
//打印奇数位
for (i = 30; i >= 0; i -=2 )
{
printf("%d", (num >> i) & 1);
}
printf("\n");
//打印偶数位
for (i = 31; i >= 1; i -= 2)
{
printf("%d", (num >> i) & 1);
}
return 0;
}
总结
本篇文章叙述了n&(n-1)和&1、>>的应用场景。