一个十进制整数转换成二进制含多少个1

1。最简单的方法:使用bitset   

unsigned count (unsigned u)
{
    bitset<32> bs(u);
    return u.count;
}

2。使用移位循环测试

unsigned count (unsigned u)
{
    unsigned ret = 0;
    while (u)
        {
        u = (u & (u - 1));    // 将 u 最右边的 1 清除,使最右边的1变成0
        ret ++;
        }
    return ret;
}

3。使用分治法

若f(n),b(n)表示 高/低 n位1出现的次数,则有f(32)=f(16)+b(16)。依照此公式依次推下去,反过来从小到大的组合起来便得到这道提的答案了。

unsigned count(unsigned u)
{
    u = (u & 0x55555555) + ((u >> 1) & 0x55555555);
    u = (u & 0x33333333) + ((u >> 2) & 0x33333333);
    u = (u & 0x0F0F0F0F) + ((u >> 4) & 0x0F0F0F0F);
    u = (u & 0x00FF00FF) + ((u >> 8) & 0x00FF00FF);
    u = (u & 0x0000FFFF) + ((u >> 16) & 0x0000FFFF);
    return u;
}
解析:

 这个二分法的原理:
用8位二进制数来做示范好了,例如 u = 10110011。
10110011  (原数)
00010001    //每两位取1位,即取偶数位, u & 01010101
01010001    //取奇数位并右移一位, (u >> 1) & 01010101
--------------(红色转化十进制为2,再看原数低二位上的1共有2个,同理其它组分别为0,2,1,从低到高看)
01100010    //上面两数相加,赋值给u,注意每两列相加的结果不会进位到第三列
00100010    //每四位取低两位, u & 00110011
00010000    //每四位取高两位并右移两位, (u >> 2) & 00110011
--------------(整个红色转化十进制为2,再看原数低四位上的1共有2个,同理高四位为3)
00110010    //上面两数相加,赋值给u
00000010    //每八位取低四位, u & 00001111
00000011    //每八位取高四位并右移四位,(u >> 4) & 00001111
--------------(整个红色转化十进制为5,再看原数所有位上的1共有5个)
00000101    //上面两数相加,赋值给u 
最终结果 u = 5。
所以其实就是不断累加的过程

你可能感兴趣的:(笔试面试)