C语言计算变量二进制中1的个数
方法一
#include <stdio.h>
unsigned char func(unsigned char para)
{
int i = 0,num = 0;
for(;i < 8;i++)
{
if(para & 0x80)
num++;
para <<= 1;
}
return num;
}
int main(void)
{
unsigned char input = 0;
printf("请输入小于等于255的值:\n");
scanf("%d",&input);
printf("输数据的二进制数中1的位数为:%d",func(input));
return 0;
}
方法一思想:定义num计算1的个数,因为形参是unsigned char型变量,所以设置8次循环,每一次拿形参的最高位和1相比(代码中的实现为para & 0x80),如果为真值(运算结果不为0即为真值),则num++,不管运算结果为什么,para都要左移一位(当前位比较过后让下一位顶替当前位成为最高位,然后再与0x80比较),8次循环完成,8个bit也就比较完成了,然后返回num作为1的个数即可。
方法二
#include <stdio.h>
unsigned char func(unsigned char para)
{
if(para & 0x01) para = para; //这句可以注释掉
if(para & 0x02) para = (para & 0xfd) + 1;
if(para & 0x04) para = (para & 0xfb) + 1;
if(para & 0x08) para = (para & 0xf7) + 1;
if(para & 0x10) para = (para & 0xef) + 1;
if(para & 0x20) para = (para & 0xdf) + 1;
if(para & 0x40) para = (para & 0xbf) + 1;
if(para & 0x80) para = (para & 0x7f) + 1;
return para;
}
int main(void)
{
unsigned char input = 0;
printf("请输入小于等于255的值:\n");
scanf("%d",&input);
printf("输数据的二进制数中1的位数为:%d",func(input));
return 0;
}
方法二思想:方法二这个思想作为面试题,我也是想了两个小时才想出来(能力有限,大神有更简单的方法欢迎指点一二)。
该函数的特点是内部不使用其他变量,这种方法可以用于极限减少栈使用的情况(不过一般也不差这点)。其思想是8个if语句用于分别判断参数
的1到8位,1的个数放在低位,如果判断为真值,那么必然1的值就+1,这时候只需要把当前位置零并加上1,那么包含当前位以下的所有位就表示1的数量。比如:
输入56 56的二进制为0011 1000
因为低三位均为0,我们直接判断第4、5、6个if语句。
先看第4个if语句:
if(para & 0x08) para = (para & 0xf7) + 1;
if条件是用于判断第4个位是否为1,明显条件成立,第4位为1。
para = 0011 1000 0xf7 = 1111 0111
para & 0xf7 + 1 = 0011 0000 + 1 = 0x0011 0001
再看第5个if语句:
if(para & 0x10) para = (para & 0xef) + 1;
if条件是用于判断第5个位是否为1,明显条件成立,第5位为1。
para = 0011 0001(语句4的运算结果) 0xef = 1110 1111
para & 0xef + 1 = 0010 0001 + 1 = 0x0010 0010
最后看第6个if语句:
if(para & 0x20) para = (para & 0xdf) + 1;
if条件是用于判断第6个位是否为1,明显条件成立,第6位为1。
para = 0x0010 0010(语句5的运算结果) 0xdf = 1101 1111
para & 0xef + 1 = 0000 0010 + 1 = 0x0000 0011
后面的7和8位均为0,就不用做比较了,结果为para = 0x0000 0011 = 3
最初的para为65(二进制为0011 1000),1的位数确实为3,结果正确。
原理不麻烦,就是表述起来繁琐而已,读者多输入数据自己验证就好了。
其他的方法还有好几种,都是很基础但是很精辟的方法,读者可以参考一下下面这篇文章,除了上面两种以外的4种方法:
C语言 统计整数二进制中表示1的个数