目录
一、统计二进制中1的个数
二、打印整数二进制的奇数位和偶数位
三、两个整数二进制位不同个数
一、统计二进制中1的个数
这是一道牛客网OJ题,感兴趣的话可以先做一遍再看解析哦 -> 牛客网的OJ链接
注意:上面的牛客网是接口型,不需要写主函数,系统默认主函数是存在的,只需要完成函数即可。
题目描述:输入一个整数 n ,输出该数32位二进制表示中1的个数。其中负数用补码表示。
思路:假设想打印一个整数的十进制的每一位,例如123,我们会先让123%10,得到3,再让123/10,得到12。然后再把12%10,以此类推就能得到它们的每一位,所以总结一下,一个整数的十进制只需循环除10和模10。然而得到二进制的每一位也是如此,只要将二进制循环模2和除2即可。例如:11的二进制为0000 1011,首先让11%2=1,这个1就是二进制序列上最后一个1,再让11/2=5,5的二进制就是101(就是上面加粗部分)。既然有思路,那我们就来看看怎么写代码吧。
按照上面的思路,不难可以写出这样的代码,但是提交发现代码错误。
举个栗子:当n = -1时,不为0进入循环,-1%2不等于1,cnt不会++,走到n /= 2,带入n的值发现n的结果为0,0为假cnt自然而然就输出0了。说明以上代码对负数是不太友好的。下面有2个办法可以解决改问题。
解决办法1:首先可以把-1当做无符号数来看待,所以只需要在int n前加上 unsigned。
解决方法2:可以运用&这个操作符( 点我,快速了解操作符)
假设有一个二进制序列为(有32位,简写):00001111,我们&上一个1就能得到最低位的1(加粗),那么问题来了,如何得到其他位上的1呢?这时位移操作符就派上用场了,只需要把00001111右移1位,然后再&上一个1即可。
最后,对于这题,我再为大家展现一个绝妙的解题方法!!
有个表达式是: n = n & (n- 1)
这是一个非常神奇的表达式,当n = 11,它的二进制为1011,n - 1 = 10,它的二进制是1010,1011 & 1010 = 1010(十进制:10),有没有发现,最低位的1不见了;接着,n - 1 = 9,它的二进制为1001,然后再让1010 & 1001 = 1000,这时,最低位的1又不见了。所以,每执行这个表达式,n的二进制最低位上的1都会消失,这个表达式执行几次,就会有多少个1。
对于上面的表达式,还能这么用
假设用编程实现n是否为2的k次方。
思路:只要是2的k次方数字,它们的2进制的表示中只有一个1
例如:2的3次方 ---- 1000
2的2次方 ---- 100
2 的 4次方 ---- 10000
这时就能灵活运用刚刚讲过的表达式:if(n & (n - 1) == 0)
二、打印整数二进制的奇数位和偶数位
题目内容:获取一个整数二进制序列中所有的偶数位和奇数位,分别打印出二进制序列。
思路:
假设要打印上图中的二进制序列的奇数位和偶数位,那么如何得到它们对应的二进制数字呢?通过上一题也不难发现,只要将(n >> i) & 1即可
代码实现:
#include <stdio.h>
void Print(int n)
{
printf("奇数位:");
int i = 0;
for (i = 31; i >= 1; i -= 2)
{
printf("%d ", (n >> i) & 1);
}
printf("\n");
printf("偶数位:");
for (int i = 32; i >= 2; i -= 2)
{
printf("%d ", (n >> i) & 1);
}
printf("\n");
}
int main()
{
int n = 0;
scanf("%d", &n);
Print(n); //封装一个Print函数
return 0;
}
三、两个整数二进制位不同个数
描述:输入两个整数,求两个整数二进制格式有多少个位不同(点我,做题!)
思路:先将n和m进行按位异或(^),此时n和m相同的二进制位清零,不同的二进制位为1,最后统计异或后结果的二进制位有几个1即可 。( 点我查看操作符详解)
#include <stdio.h>
int one(int m,int n)
{
int cnt = 0;
int tmp = m ^ n;
while(tmp)
{
tmp = tmp & (tmp - 1);
cnt++;
}
return cnt;
}
int main()
{
int m = 0;
int n = 0;
scanf("%d %d",&m,&n);
int res = one(m,n);
printf("%d\n",res);
return 0;
}
四、总结
阳康后第一篇博客,欢迎大佬们指点,后面开始继续输出。加油!!!