【100题】第二十八 整数的二进制表示中1的个数

一,题目:输入一个整数,求该整数的二进制表达中有多少个1

                  例如输入10,由于其二进制表示为1010,有两个1,因此输出2

二,分析:
        这是一道很基本的考查位运算的面试题。

        菜鸟思考:利用除法,和取余运算计算出10进制数的二进制表示后,统计1的个数

三,代码

自己测试代码(感觉没问题)

#include <iostream>
using namespace std;
int  count_of_one(int n)
{
	int count=0;
	while(n)
	{
		if(n%2==1)
			count++;
		
		n=n/2;
	}
	return count;
}
int main()
{
	cout<<count_of_one(16)<<endl;
	return 0;
}
查询各方资料,多次杀死脑细胞后,发现:如果为负数的话将导致错误发生

改进后:

#include <iostream>
using namespace std;
int  count_of_one(int a)
{
	int count=0;
	int n;
	if(a>0)
	   n=a;
    else
       n=-a;
	while(n)
	{
		if(n%2==1)
			count++;
		
		n=n/2;
	}
	if(a>0)
	  return count;
    else
      return count+1;
}
int main()
{
	cout<<count_of_one(-10)<<endl;
	return 0;
}

四,升级版(除法的效率比移位运算要低的多,

       先判断整数的最右边一位是不是1接着把整数右移一位,原来处于右边第二位的数字现在被移到第一位了,再判断是不是1
这样每次移动一位,直到这个整数变成0为止。现在的问题变成怎样判断一个整数的最右边一位是不是1了。
很简单,如果它和整数1作与运算。由于1除了最右边一位以外,其他所有位都为0因此如果与运算的结果为1,表示整数的最右边一位是1,否则是0

得到的代码如下:

int NumberOf1_Solution1(int i)
{
      int count = 0;
      while(i)
      {
            if(i &1)
                 count ++;
           i = i >> 1;  //是相对于二进制数,向右移动一位,等价于除以2
      }
      return  count;
}

在实际编程中如果可以应尽可能地用移位运算符代替乘除法。 

这个思路当输入i是正数时没有问题,但当输入的i是一个负数时,不但不能得到正确的1的个数,还将导致死循环。以负数0x80000000为例,右移一位的时候,并不是简单地把最高位的1移到第二位变成0x40000000而是0xC0000000。这是因为移位前是个负数,仍然要保证移位后是个负数,因此移位后的最高位会设为1如果一直做右移运算,最终这个数字就会变成0xFFFFFFFF而陷入死循环。为了避免死循环,我们可以不右移输入的数字i首先i1做与运算,判断i的最低位是不是为1接着把1左移一位得到2,再和i做与运算,就能判断i的次高位是不是1……这样反复左移,每次都能判断i的其中一位是不是1。基于此,我们得到如下代码:

int NumberOf1_Solution2(int i)
{
      int count = 0;
      unsigned int flag = 1;
      while(flag)
      {
            if(i &flag)
                 count ++;
           flag = flag << 1;
      }
      returncount;
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值