【编程之美】求二进制数中1的个数

对于一个字节的变量,求其二进制表示中“1”的个数,要求算法的执行效率尽可能地高。


分析与解法:

【解法一】

可以举一个八位的二进制例子来进行分析。对于二进制操作,除以一个2,原来的数字将会减少一个0。如果除的过程中有余,那么就表示当前位置有一个1。

  以10 100 010 为例:

第一次除以2时,商为1 010 001,余为0。

第二次除以二时,商为 101 000,余为1。

因此可以考虑利用整数数据除法的特点,通过想除和判断余数的值来进行分析。


代码如下:

int Count (int v)

{

int num=0;

while(v)

{

if (v%2==1)

num++;

v=v/2;

}

return num;

}


【解法二】

前面的代码看起来比较复杂。我们知道,向右移位操作同样也可以达到相除的目的。唯一不同之处在于,以为之后如何来判断是否有1存在。对于这个问题,再来看一看一个八位的数字:10 100 001。

在向右以为的过程中,我们会把最后一位直接丢弃。因此需要判断最后以为是否为1,而“与”操作可以达到目的。可以把这个八位的数字与0000 0001 进行“与”操作。如果结果为1,则表示当前八位数的最后一位为1,否则为0.


代码如下:

int  Count(int v)

{

int num=0;

       while(v)

{

v+=v&0x01;

v>>=1;

}

return num;

}


【解法三】

位操作比除、余操作的效率高了很多。但是,即使采用位操作,时间复杂度认为O(log2 v),log2v为二进制数的位数。那么还能不能再降低一些复杂度呢?如果有办法让算法的复杂度只与“1”的个数有关,复杂度不就能进一步降低了吗?

同样用10 100 001来举例。如果只考虑和1的个数相关,那么,我们是否能够在每次判断中,仅与1来进行判断呢?

为了简化这个问题,我们只考虑只有一个1的情况。例如:01 000 000。如何判定给定的二进制数里面有且仅有一个1呢?可以通过判断这个数是否是2的整数次幂来实现。另外,如果只和这一个“1”进行判断,如何设计操作呢?我们知道的是,如果进行这个操作,结果为0获为1,就可以得到结论。

如果希望操作后的结果为0,01 000 000可以和00 111 111进行“与”操作。这样要进行的操作就是 01 000 000&(01 000 000-00 000 01)=01 000 000&00 111 111=0。

代码为:

int Count(int v)

{

int num=0;

while(v)

{

v&=(v-1);

num++;

}

return num;

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值