壁仞科技一面

求64位二进制整数里1的个数,即实现 __builtin_popcount 函数
本来觉得忘了的,甚至想放弃,比划比划写着写着就写出来了

#include <iostream>
using namespace std;

int countOnes_v1(unsigned long u){
    int c=0;
    while(u){
        c++;
        u=u&(u-1);
    }
    return c;
}

int countOnes_v2(unsigned long u){

    unsigned long a1 = u&0x5555555555555555;
    unsigned long a2 = u&0xAAAAAAAAAAAAAAAA;
    u=(a2>>1)+a1; // 每2位上为1表示有一个1,为10表示有2个1
    
    a1 = u&0x3333333333333333;
    a2 = u&0xCCCCCCCCCCCCCCCC;
    u = (a2>>2)+a1; // 每4位有效
    
    a1 = u&0x0F0F0F0F0F0F0F0F;
    a2 = u&0xF0F0F0F0F0F0F0F0;
    u = (a2>>4)+a1; // 每8位有效
    
    a1 = u&0x00FF00FF00FF00FF;
    a2 = u&0xFF00FF00FF00FF00;
    u = (a2>>8)+a1; // 每16位有效
    
    a1 = u&0x0000FFFF0000FFFF;
    a2 = u&0xFFFF0000FFFF0000;
    u = (a2>>16)+a1; // 每32位有效
    
    a1 = u&0x00000000FFFFFFFF;
    a2 = u&0xFFFFFFFF00000000;
    u = (a2>>32)+a1; // 每64位有效
    
    return u;
}

int main()
{
    cout << countOnes_v1(0xFFFFFFFFFFFFFFFF)<<"\n";// 4+3+2+1=10
    cout << countOnes_v2(0xFFFFFFFFFFFFFFFF)<<"\n\n";
    
    cout << countOnes_v1(0x0000000000000000)<<"\n";// 4+3+2+1=10
    cout << countOnes_v2(0x0000000000000000)<<"\n\n";
    
    cout << countOnes_v1(0x1010101010101010)<<"\n";// 4+3+2+1=10
    cout << countOnes_v2(0x1010101010101010)<<"\n\n";
    
    cout << countOnes_v1(0x0101010101010101)<<"\n";// 4+3+2+1=10
    cout << countOnes_v2(0x0101010101010101)<<"\n\n";
    
    cout << countOnes_v1(0x0A0A0A0A0A0A0A0A)<<"\n";// 4+3+2+1=10
    cout << countOnes_v2(0x0A0A0A0A0A0A0A0A)<<"\n\n";
    return 0;
}

面试官好像在干别的事,抛个问题出来然后就没管了,等我说完继续抛个问题…
写完后也有一段沉默,我也有自知之明,得拖满45分钟,互不干扰,就继续再改改
后来看差不多45了就提醒一下写完了,后问了从哪些角度测试,加了一些样例。
本来说做两个题的,后来这题我写了挺久就没出了。

更优雅的写法。。。。

__builtin_popcount(num) // 二进制中1的个数
int count(int num) {
    num = (num & 0x55555555) + ((num >> 1) & 0x55555555); // 相邻两位上的1的和存在这两位上
    num = (num & 0x33333333) + ((num >> 2) & 0x33333333); 
    num = (num & 0x0F0F0F0F) + ((num >> 4) & 0x0F0F0F0F);
    num = (num & 0x00FF00FF) + ((num >> 8) & 0x00FF00FF);
    num = (num & 0x0000FFFF) + ((num >> 16) & 0x0000FFFF);
    return num;
}

C++ 编程记忆

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Bugs清道夫

来自清道夫的谢意,susga

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值