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;