天天看点

求二进制数中1的个数(编程之美)

求二进制数中1的个数

继京东618店庆时买的《编程之美》这本书,翻了翻,发现里面的题还是挺有意思的,看起来我们觉得很简单的题目,解法却有很多很多种,真是一个比一个巧妙,于是,决定记录一下。

书中的题目如下

  • 对于一个字节(8bit)的无符号数,求其二进制表示中“1”的个数,要求算法的执行效率尽可能高。

就像书中给我们说的一样,我们一般人可能想到的解决方法如下

int countOne(int n){
 int count=;
 while(n){
     if(n%==){
         count++;
    }
     n/=;
 }
 return count;
}
           

然后,有的人可能说我采用移位的方式来解决,但这种方法与上面的方法随大同小异,但在效率上有很大的提升,这是因为移位操作较除、余操作要快。

文章中提到的第三种方法如下:这种方法实在是很巧妙,想不到

int countThree(int n){
    int count=;
    while(n){
        n&=(n-);//与一次就可以消掉n中最右边的“1”,因此也就可以统计出来
        count++;
    }
}
           

文章中提到的第四种方法:查表法(以空间换取时间),通过空间来换取时间是一个比较常用的方法。

由于8bit的表太长,这里选取的是4bit的表的例子如下

int count_bit4(int n)
{
     int countTable[] = 
    {
        , , , , 
        , , , , 
        , , , , 
        , , , 
    } ;

     int count = ;
    while (n)
    {
    /*即将无符号数n以4位为一组进行“1”的查表统计
    */
        count += countTable[n &] ;
        n >>= ;
    }
    return count ;
}
           

根据上面的程序,无论我们的变量n时32为的,还是16为都可以快速的统计出n的二进制数中“1”的个数,这也就解决了《编程之美》2.1节后面的第一个问题。第一个问题如下:

  • 如果变量时32为的DWORD,你会使用上述的哪一种算法,或者改进哪一种算法?

第二题

  • 判断整数A和B的二进制表示中有多少位是不同的?

也比较简单:先进行异或,然后再判断异或所得结果中“1”的个数