计算一个数的二进制中1的个数(三种方法保姆级详解~)

计算一个数的二进制中1的个数(三种方法保姆级详解~)

写一个函数返回参数二进制中 1 的个数。

比如: 15 0000 1111 4 个 1

方法一:遍历二进制位

暴力求解,拿到这个数的二进制中的每一位,通过移位运算,让最低位按位与1。

运算规则:只有两个数的二进制同时为1,结果才为1,否则为0。(负数按补码形式参加按位与运算)

int number_of_1(int m)

{

int count = 0;

int i = 0;

for (i = 0; i < 32; i++)

{

if (((m >> i) & 1) == 1)

count++;

}

return count;

}

int main()

{

int n = 0;

scanf("%d", &n);//15

int ret = number_of_1(n);

printf("%d\n", ret);//4

return 0;

}

运行结果:若n为15,结果为:4;

若n为-1,结果为:32

方法二:取模运算

从十进制中,我们可以知道一个数对10取模就可以得到最低位的数字,例如123%10=3,想要得到2,只需要让123/10=12,12%10=2,让12/10=1,1%10=1,这样123的每一位都被获得了。

对付二进制的数,想要拿到每一位,依然可以同理操作,例如15%2=1,这一步拿到第一个1,15/2=7,7%2=1,这次拿到第二个1,7/2=3,3%2=1,这里拿到第三个1,3/2=1,1%2=1,这是最后一个1,下一步是1/2=0,可知这个数的二进制位已经被拿完了,不需要再往下计算。(每次得到一个余数,就往下除进制数,二进制除2,十进制除10)

需要注意的是,传参过来的是int类型,如果用int接收有符号整数,比如说,-1在while循环里,进行if语句判断一定不等于1,对负数是没办法统计1的个数的。形参接收的部分需要改为无符号整型unsigned int才可以,他会把负数中最高位的符号位当作一个大的正数处理。

int number_of_1(unsigned int m)

{

int count = 0;

while (m)

{

if (m % 2 == 1)

count++;

m /= 2;

}

return count;

}

int main()

{

//-1

//10000000000000000000000000000001 -- 原码

//11111111111111111111111111111110 -- 反码

//11111111111111111111111111111111 -- 补码 32个1

int n = 0;

scanf("%d", &n);

int ret = number_of_1(n);

printf("%d\n", ret);//输入-1,所得到的结果为32

return 0;

}

方法三:巧妙按位与

这里介绍一个神奇的公式, n = n&(n-1); 这个表达式会让n的二进制中最右边的1就消失了。(不妨大家在纸上举例几个数据进行验证一下,这里不过多解释)

这种方法大大提高了代码效率,有多少个1,循环就进行多少次。不需要像方法一那样,不管数字有几个1都要循环32次,也不需要像方法二考虑传参类型。

int number_of_1(int m)

{

int count = 0;

while (m)

{

m = m & (m - 1);

count++;

}

return count;

}

相关推荐

油猴js脚本怎么导入
microsoft365版本

油猴js脚本怎么导入

📅 07-18 👁️ 6272
知道对方手机号却加不上微信?3种方法帮你轻松搞定!
365网站不给出款怎么办

知道对方手机号却加不上微信?3种方法帮你轻松搞定!

📅 07-01 👁️ 7057
Far Cry Franchise
microsoft365版本

Far Cry Franchise

📅 08-27 👁️ 7726