目录
如何得出二进制的每一位?
在思考之前,回忆如何得出十进制中的每一位?
如:1234
1234 % 10 = 4
1234 / 10 = 123
-----
123 % 10 = 3
123 / 10 = 12
-----
12 % 10 = 2
12 / 10 = 1
-----
1 % 10 = 1
1 / 10 = 0
同理:
二进制的每一位可以通过 %2 和 /2 得到
如:11
11 % 2 = 1
11 / 2 = 5
-----
5 %2 = 1
5 / 2 = 2
-----
2 % 2 = 0
2 / 2 = 1
-----
1 % 2 = 1
1 / 2 = 0
所以11的二进制位:1101
写一个函数返回参数二进制中1的个数
方法一(常规)
#include <stdio.h>
int count_num_of_1(int num)
{
int count = 0;//用来记录1的个数
while (num)
{
if ((num % 2) == 1)
{
count++;
}
num /= 2;
}
return count;
}
int main()
{
int num = 0;
scanf("%d", &num);
int ret = count_num_of_1(num);
printf("%d", ret);
return 0;
}
当输入-1时,结果为0
-1
补码:11111111111111111111111111111111
所以,-1的二进制中应该有32个1
但在代码中,-1进入函数
-1 % 2 = -1
-1 / 2 = 0
最后num = 0,循环停止
完善
int count_num_of_1(unsigned int num)
只需传数时,传入无符号数,那么就会将-1的11111111111111111111111111111111看作是非常大的正数
结果为32
方法二(位操作符)
位操作符 按位与 & - 全1是1
#include <stdio.h>
int count_num_of_1( int num)
{
int i = 0;
int count = 0;
for (i = 0; i < 32; i++)
{
if (((num >> i) & 1) == 1)
{
count++;
}
}
return count;
}
int main()
{
int num = 0;
scanf("%d", &num);
int ret = count_num_of_1(num);
printf("%d", ret);
return 0;
}
思路:
通过数字的补码的右移 i 位,遍历了所有的二进制位
然后&1,看最后1个二进制位是否为1
这个代码对给出的正负数,都可以计算二进制中的1的个数
方法三(位操作符 - 进阶)
num = num & (num -1)
执行1次,去掉一个1
如:num = 15
1111 num
1110 num - 1
-----
1110 num
1101 num - 1
-----
1100 num
1011 num - 1
-----
1000 num
0111 num - 1
-----
0000 num
#include <stdio.h>
int count_num_of_1( int num)
{
int count = 0;
while (num)
{
num = num & (num - 1);
count++;
}
return count;
}
int main()
{
int num = 0;
scanf("%d", &num);
int ret = count_num_of_1(num);
printf("%d", ret);
return 0;
}
思路:
num = num & (num - 1)
每次二进制位最右边的数变成0,后面的0借位变成1,这样才是-1
比如:1100(2² + 2³ = 12)
变成:1011(2⁰ + 2¹ + 2³ = 11)