求二进制中1的个数

题目:请事先一个函数,输入一个整数,输出该数二进制中表示1的个数。例如,把9表示成二进制1001,有2位是1。因此,如果输入9,则该函数输出2。

1、位运算知识补充
位运算共有5种运算:与、或、异或、左移和右移。
(1)与、或和异或的运算规律
这里写图片描述

(2)左移
m<

例:0000 1010B = 10d;1000 1010B = -10d 
1)(无符号)0000 1010 << 2 = 0010 1000 = 40;
2)(有符号)1000 1010 << 2 = 1010 1000 = -40;

(3)右移
m>>n表示m右移n位。即,最右边丢弃,左边补0。如果是符号数,则右边丢弃,左边补满符号数,如:正数右移n位,左边补n个0;负数右移n位,左边补n个1。

1)(无符号)0000 1010 >> 2 = 0000 0010;
2)(符号)  0000 1010 >> 2 = 0000 0010;
3)(符号)  1000 1010 >> 2 = 1110 0010;

2、解题方法
方法一:
(1)步骤:
1)判断输入的数是否大于1,即:为真。
2)判断该数的二进制数的最右边的数是否为1,为1则计1,否则向右移。
3)再重复步骤2,直到整个整数为1为止。

(2)注意:判断整数的二进制的最右边的数是否为1,只要把整数和1做与运算(n & 1),看结果就可以知道了。

(3)程序:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>

int BinaryNumOf1(int num)
{
    int count = 0;
    while (num)
    {
        if (num & 1)
        {
            count++;
        }
        num = num >> 1;
    }
    return count;
}

int main()
{
    int num = 10;
    int ret = BinaryNumOf1(num);
    printf("%d\n", ret);
    system("pause");
    return 0;
}

(4)运行结果:
1)当整数为10时
这里写图片描述

2)当整数为-10时
这里写图片描述

释:程序会陷入无限循环,因为当输入的数为负数进行右移时,左边要补符号数。如:-10d = 10000000 00000000 00000000 00001010B,右移一位就变成了11000000 00000000 00000000 00000101,再右移一位就变成了11100000 00000000 00000000 00000010,依次变化下去,最终将变成0xFFFFFFFF而陷入无限循环。

方法二:
方法二相比方法一做的变化是:输入的整数不动,将比较数1进行左移,再与该整数进行与运算。
(1)步骤:
1)整数n和1进行与运算,结果为真则计1;
2)将1进行左移(为2)再和n进行与运算,结果为真则计1;
3)依次循环,直到最后。

(2)程序:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
int BinaryNumOf1(int num)
{
    int count = 0;
    int flag = 1;
    while (flag)
    {
        if (num & flag)
        {
            count++;
        }
        flag = flag << 1;
    }
    return count;
}

int main()
{
    int num = -10;
    int ret = BinaryNumOf1(num);
    printf("%d\n", ret);
    system("pause");
    return 0;
}

(3)运行结果:
1)输入的数为10
这里写图片描述

2)输入的数为-10
这里写图片描述

方法三:
方法三是对方法二的改进和优化。因为在方法二中,循环的次数等于整数二进制的位数,32位的整数需要循环32次。而在方法三中,输入的数的二进制中有多少个1就执行多少次。

(1)解题思想
把一个数减去1,再与原来的数进行与运算,将能把最右边的1变成0。这样,一个整数的二进制中有多少个1,就执行多少次。

(2)程序

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>

int BinaryNumOf1(int num)
{
    int count = 0;
    while (num)
    {
        count++;
        num = num & (num - 1);
    }
    return count;
}

int main()
{
    int num = -10;
    int ret = BinaryNumOf1(num);
    printf("%d\n", ret);
    system("pause");
    return 0;
}

(3)运行结果
1)输入的数为10
这里写图片描述

2)输入的数为-10
这里写图片描述

注:把整数右移一位和除以2在数学上是等价的,但是移位的效率要比除数的效率要高。

猜你喜欢

转载自blog.csdn.net/m0_38121874/article/details/80139608