题目:请事先一个函数,输入一个整数,输出该数二进制中表示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在数学上是等价的,但是移位的效率要比除数的效率要高。