1.计算一个数字二进制补码里面1的个数
(1)方法一
根据这个10进制的整数,对这个数进行%10,/10不断地进行下去,
%10得到最后一位,/10得到舍去最后一位之后剩余的数;
同理得到:二进制就进行%2/2的操作,不断地进行下去,
%2==1就计数,否则就/2,知道结果是0就退出循环;
int countone(unsigned int m)
{
int count = 0;
while (m)
{
if (m % 2 == 1)
{
count++;
}
m = m / 2;
}
return count;
}
int main()
{
int n = 0;
scanf("%d", &n);
int ret = countone(n);
printf("%d\n", ret);
return 0;
}
这个里面传参类型设置成unsigned int是因为-1这个特例
但是如果直接输入-1,-1%2不是1,-1/2=0就会直接跳出循环,无法正常计数,所以转换成为无符号整形;
(2)方法二
int countone(int m)
{
int count = 0;
int i = 0;
for(i=0;i<32;i++)
{
if ((m>>i) & 1 == 1)
{
count++;
}
}
return count;
}
这里的m右移i位和1进行按位与运算,32个比特位构成一个循环,依次进行判断输出最后的个数;
(3)方法三
通过这个我们发现m&(m-1)每次都能去掉二进制序列里面后面的一个数字1,这样就可以有几个1就进行几次循环,大大的提高了效率,相比于第二种方法很快,因为第二种无论是否为0都要进行判断,而这种只需要判断是0的数位,但是这种方法难以想到;
int countone(int m)
{
int count = 0;
while (m)
{
count++;
m = m & (m - 1);
}
return count;
}
这里要先进行加加操作,然后每一次就减少一个0;
2.把一个数字的二进制位的某一位0变成1再变成0
#include <stdio.h>
int main()
{
int a = 13;
a = a | (1<<4);
printf("a = %d\n", a);
a = a & ~(1<<4);
printf("a = %d\n", a);
return 0;
}
比如10:00000000 00000000 00000000 00001010把第5位变成0再恢复1
(1)变成0就是把把1左移4位,进行按位或操作,0变为1,后面的和0或操作,1还是1,0还是0,无影响;
(2)再变成0就是做以后取反和a进行按位与操作,原为数字1就变为0其他的和1进行,1还是1,0还是0
换成其他的数字,该方法也是用,只是需要左移n-1位,n是题目要求的第几位数字,这个例子第五
位进行变化,就左移4位
3.输入2个数字,判断他们的二进制位不同的位数
(1)先进行按位异或,相同就是0,不同就是1;
(2)统计1的个数,就回到了第一题的方法;
#include <stdio.h>
int main(){
int a=0;
int b=0;
int c=0;
int count=0;
while(scanf("%d %d",&a,&b)!=EOF)
{
c=a^b;
while(c)
{
c=c&(c-1);
count++;
}
}
printf("%d",count);
return 0;
}
4.分别打印一个数字的二进制序列的奇数位和偶数位数字
void Printbit(int num)
{
for (int i = 31; i >= 1; i -= 2)
{
printf("%d ", (num >> i) & 1);
}
printf("\n");
for (int i = 30; i >= 0; i -= 2)
{
printf("%d ", (num >> i) & 1);
}
printf("\n");
}
int main()
{
int m = 0;
scanf("%d", &m);
Printbit(m);
return 0;
}
这个主要难在如何打印:
(1)是1就打印1,是0就打印0;
(2)将这个二进制序列右移并和1进行按位与运算
例如:第一位是奇数位,向右移动31位,和1进行按位与运算,是1就打印1,是0就打印0;