C语言学习!
1. 统计二进制中1的个数。
写一个函数返回参数二进制中1的个数,
比如:输入15 (0000 1111) 二进制有4个1,输出4.
方法1
编程思路:
得到十进制数字的每一位操作:
- 如1234
- 1234 % 10就可以得到原数字1234个位的4
- 1234 / 10就可以去掉原数字1234个位的4得到123
- 123 % 10就可以得到原数字1234十位的3
- 123 / 10就可以去掉原数字1234十位的3得到12
- 12 % 10就可以得到原数字1234百位的2
- 12 / 10就可以去掉原数字1234百位的2得到1
- 1 % 10就可以得到原数字1234千位的1
- 1 / 10就可以去掉原数字1234千位的1得到0
- 当数值为0时,不再计算。
最终就可以得到原数字1234的每一位数1、2、3、4。
得到二进制数字的每一位,可以参考上述方法
- 如十进制数11的二进制数为1011
- 11 % 2就可以得到1011最低位的1
- 11 / 2 = 5就可以去掉原数字1011最低位的1得到101
- 5 % 2就可以得到1011第二位的1
- 5 / 2 = 2就可以去掉原数字1011第二位的1得到10
- 2 % 2就可以得到1011第三位的0
- 2 / 2 = 1就可以去掉原数字1011第三位的0得到1
- 1 % 2就可以得到第四位的1
- 1 / 2 = 0就可以去掉原数字1011第四位的1
- 当数值为0时,不再计算。
最终就可以得到二进制数1011共有3个。
代码示例:
#include <stdio.h>
int Count_num(unsigned int n)
{
int count = 0;
while (n != 0)
{
if (n % 2 == 1)
{
count++;
}
n /= 2;
}
return count;
}
int main()
{
int Num = 0;
scanf("%d", &Num);
int a = Count_num(Num);
printf("%d\n", a);
return 0;
}
运行结果:
15
4
-1
32
但是这个方法计算负数的二进制1的个数需要注意。
例如-1
- 1000 0000 0000 0000 0000 0000 0000 0001 原码
- 1111 1111 1111 1111 1111 1111 1111 1110 反码
- 1111 1111 1111 1111 1111 1111 1111 1111 补码
-1在内存中是以补码的形式存放的,如果调用函数传参将有符号数-1当做为无符号数来看,就不会将数(-1补码)首位的1当做负数的符号位来看,而是将数(-1补码)当做一个很大的二进制数来看,就可以得到-1二进制数中1的个数。
所以这里函数参数为无符号整型。
方法2
一个数按位与1就可以得到一个数二进制位的最低位是几,让数的每一位都按位与1,就可以得到数二进制中1的个数。
代码示例:
#include <stdio.h>
int Count_num(int n)
{
int i = 0;
int count = 0;
for (i = 0; i < 32; i++)
{
if (((n >> i) & 1) == 1)
{
count++;
}
}
return count;
}
int main()
{
int Num = 0;
scanf("%d", &Num);
int a = Count_num(Num);
printf("%d\n", a);
return 0;
}
运行结果:
15
4
-1
32
方法3
用表达式:n=n&(n-1) 来巧妙计算
代码示例:
#include <stdio.h>
int Count_Num(int n)
{
int count = 0;
while (n)
{
n = n & (n - 1);
count++;
}
return count;
}
int main()
{
int Num = 0;
scanf("%d", &Num);
int n = Count_Num(Num);
printf("%d\n", n);
return 0;
}
运行结果:
15
4
-1
32
代码原理:
例如:n=15,表达式与表达式对应的二进制数值如下
第一次循环
- 1111 n
- 1110 n-1
- 1110 n & (n - 1)
第二次循环
- 1110 n = n & (n - 1)
- 1101 n-1
- 1100 n & (n - 1)
第三次循环
- 1100 n = n & (n - 1)
- 1011 n-1
- 1000 n & (n - 1)
第四次循环
- 1000 n = n & (n - 1)
- 0111 n-1
- 0000 n & (n - 1)
当n=0时,二进制数中就没有1了,在n=0之前,表达式n = n & (n - 1)执行过几次,原数n的二进制数就有几个1,因为表达式执行一次去掉二进制数最右边的一个1.
2.求两个数二进制中不同位的个数。
两个int(32位)整数m和n的二进制表达式中,有多少个位(bit)不同。
方法1
m和n每一位都按位与1后比较是否相等。
代码示例:
#include <stdio.h>
int Count_diff_bit(int m, int n)
{
int count = 0;
int i = 0;
for (i = 0; i < 32; i++)
{
if (((m >> i) & 1) != ((n >> i) & 1))
{
count++;
}
}
return count;
}
int main()
{
int m = 0;
int n = 0;
scanf("%d %d", &m, &n);
int ret = Count_diff_bit(m, n);
printf("%d", ret);
return 0;
}
运行结果:
15
1
3
1
-1
31
方法2
求出m与n异或的值后,再计算所得值的二进制位1的个数。
异或:相同为0,不同为1.
代码示例:
#include <stdio.h>
int Count_diff_bit(int m, int n)
{
int count = 0;
int num = n ^ m;
while (num)
{
num = num & (num - 1);
count++;
}
return count;
}
int main()
{
int m = 0;
int n = 0;
scanf("%d %d", &m, &n);
int ret = Count_diff_bit(m, n);
printf("%d", ret);
return 0;
}
运行结果:
15
14
1
15
-1
28