一、方法①:对每个比特位进行检查
1.1 实现思路:
要计算一个数的二进制中1的个数,我们先要了解怎样判断二进制中一个比特位上是1还是0。为了达到这个目的,我们就要借助位运算符“按位与&”和数字“1”。
按位与的功能是参与运算的两数各对应的二进位相与。只有对应的两个二进位都为1时,结果位才为1。
所以当按位与&与1结合起来,我们就能够判断一个数字的二进制最右边的比特位上是0还是1。如果最右边的比特位上为1,则按位与1的结果为1,如3 & 1 = 1;反之则为0,如2 & 1 =0;
我们解决了对最右边比特位的检查,就要解决对其他位置的检查。其实这个问题很简单,只需要利用右移运算符“>>”把其余位置挪动到最右边就行了。
1.2 代码实现:
#include <stdio.h>
int main()
{
int num = 0;
scanf("%d", &num);
int count = 0;
int i = 0;
//因为num的数据类型为int 大小为4个字节 共32个比特位 所以最多要移动31个比特位 故i < =31
//如果num的数据类型位long long 则i <= 63
for (i = 0; i <= 31; ++i)
{
if ((num >> i & 1) == 1)
{
++count;
}
}
printf("%d\n", count);
return 0;
}
二、方法②:n = n&(n-1)
2.1 实现思路:
你看见n&(n-1)这个标题你可能会感到疑惑,这个式子这有什么用吗?
那我可以很确信的告诉你,它确实有用。n = n&(n-1)可以消除n的二进制中的一个1。这么说比较抽象,我们可以来看看图。
n = n&(n-1)每进行一次,就会把n二进制形式中的一个1消除, 所以想要计算一个数二进制中有多少个1时,我们就可以计算在n变为0(0的二进制全为0)之前会进行几次n = n&(n-1)。
2.2 代码实现:
#include <stdio.h>
int main()
{
int num = 0;
scanf("%d", &num);
int count = 0;
while (num != 0)
{
num = num & (num - 1);
++count;
}
printf("%d\n", count);
return 0;
}
2.3 与方法一相比的优势:
方法一的实现,需要对二进制位中的每个位进行检查,这难免会造成资源浪费。比如我们要检查数字1的二进制中有多少个1,方法一需要检查把32个(long long 类型为64个)比特位每个都检查一遍才能得出答案,但其实我们知道,最少只要检查一遍就行,因为1的二进制中只有一个1。
方法二就能够做到最小程度的检查,因为方法二的原理就决定了,一个数中有多少个1,就会检查多少次,这样就不会造成不必要的消耗。
因此,方法二的效率比方法一更高。
三、方法③:逻辑右移">>>"(Java)
3.1 实现思路:
java相比C语言多了逻辑(无符号)右移这一运算符。
逻辑右移就是不考虑符号位,当右移一位时,左边补零即可。
算术右移需要考虑符号位,当右移一位时,若符号位为1,就在左边补1;否则,就补0。
例如,8位二进制数11001101分别右移一位。
逻辑右移就是01100110
算术右移就是11100110
逻辑右移与算术右移的区别主要体现在操作数为负数时。如果操作数为-1,当进行的是逻辑右移时,那么最后-1会变成0,我们可以在这个过程中将右移后的数&1来计算1的个数;而当进行的是算数右移时,-1是不会变成0的,因为-1的符号位为1,每右移一次,左边就会补1,这样就永远不可能变成0。
3.2 代码实现:
public static void BinaryCode1Count() {
Scanner scanner = new Scanner(System.in);
int count = 0;
System.out.println("请输入一个数");
int num = scanner.nextInt();
int record = num;
while (num != 0) {
if ((num & 1) == 1) {
++count;
}
num >>>= 1;
}
System.out.println(record + "的二进制中有" + count + "个1");
scanner.close();
}
3.3 与方法一相比的优势
方法三与方法一很像,但是方法三比方法一更好。方法三不仅不需要我们手动来控制循环的次数,还能够在n为正数时减少循环的次数。方法三判断的次数与二进制中最左边的1的位置挂钩,我们以9(0000 1001)来观察。这里把最右边当作第一位,如果是方法一,就需要判断8次才能得到答案;但是如果是方法二,因为最左边的1在第四位,那么就只需要判断4次就能得到答案。
所以说,方法三比方法一更好,但不及方法二。
四、小结
这里是我总结的三种计算一个数的二进制的1的个数的方法,希望能够对你有所帮助。
如有错误,还请指正!