这是个很简单的小编程题目,但频繁的出现在几场笔试中,自己便试着寻求他的多种实现方法,最后总结出了如下四个,思路大致相同:
1.通过模2判断最后一位是否为1,为1则COUNT++,然后除2(相当与将该数右移一位),循环;最终求出结果。
实现如下:(C实现)
#include<stdio.h>
void main()
{
int i,count=0;
i=15;
do
{
if((i%2)!=0) //判断末尾是否为1
{
count++; //末尾为1则count++
}
i=i/2; //i除2,相当于右移一位
}while(i>=1);
printf("1的个数为%d\n",count); //输出结果
}
2.通过与0x00000001进行&操作,判断该数末尾是否为1,为1则count++,然后右移一位,循环。
实现如下:
//这里我算的是signed int的2进制表示含1的个数,负数则转换成正数来计算
#include<iostream>
using namespace std;
int count(signed x);
int main()
{
signed x;
cout<<"please input a number:";
cin>>x;
cout<<count(x)<<endl;
return 1;
}
int count(signed x) //count函数对X含多少个1计数
{
int a,i=0;
a=1;
if(x<0) x=-x; //x小于0则把x转换成正数,也可以用x=~(x-1);替换
while(x){
if(x&a){ //若x最低位为1,i++
i++;
}
x>>=1; //x向右移一位,x为正,向左边填0
}
return i; //返回x中1的个数
}
3.使用bitset库。
实现如下:
#include <iostream>
#include <bitset>
using namespace std;
int main()
{
int N;
cin>>N;
bitset<32> _N=N; //定义一个32位的bitset类对象
int num=0;
for(int i=0;i<_N.size();i++)
if(_N[i]) //循环判断_N的每位是否为1
num++; //计数
cout<<num<<endl;
return 0;
}
4.最后这个方法是最奇妙的,因为它没有用循环来做,是我从网上搜到的,算法思想我自己也没搞明白,先贴出来。
实现如下:
int count(unsigned x)
{
x = x - ((x >> 1) & 0x55555555); //保留x奇数数位(1、3、5..)上的1
x = (x & 0x33333333) + ((x >> 2) & 0x33333333); //
x = (x + (x >> 4)) & 0x0F0F0F0F;
x = x + (x >> 8);
x = x + (x >> 16);
return x & 0x0000003F;
}
有明白的朋友也跟我解释下。