位运算:二进制中1的个数12

位运算:是把数字用二进制表示之后,对每一次是0或1的运算。

乘除效率低,实际编程中尽可能的用移位运算代替乘除法。

世界上有10中人,一种人知道二进制,而另一种人不知道二进制……

五种位运算:与、或、异或、左移和右移,分别对应&、 |、 ^、<<、 >>。
异或:相同为0, 相异为1。

左移运算符m左移n,表示把m左移n位, 最左边的n位将被丢弃。

右移要复杂些,右移时处理最左边位: 如果数字是一个无符号数值,则用0填补最左边的n位。 如果数字是一个有符号数值, 则用数字的符号位填补最左边的n位; 即如果数字原先是正数,则用数字的右移之后最左边补n个0; 若为负数补n个1。

求二进制中1的个数
题目描述:实现一个函数, 输入一个整数,输出该二进制表示中1的个数。 例如把9表示成二进制是1001, 有2位是1。因此如果输入9, 则函数输出2。

解题思路:

  1. 将n与0001进行或操作,为true则计数,否则右移1位,知道n为0。此方法如果输入是负数, 容易造成死循环。
  2. 解法1:我们不采用上面的方法。而是使用一个标记,初始化为1,对1做左移,然后与n做与&操作。知道1为0,这种解法的循环次数等于整数二进制的位数。即32位二进制循环32次。
  3. 解法2:此方法可以在有几个1的情况下就循环几次。原理:把一个整数减去1,再和原来整数做运算,会把该整数最右边一个1变成0.那么一个整数的二进制表示中有多少个1, 就可以进行多少次这样的操作。

测试用例:

int main(){
    //整数
    int number = 9;
    //1的个数
    int counts = 0;
    //结果
    counts = NumberOf1(number);  //使用解法2
    //输出结果
    std::cout << counts;  //Output: 2 

    return 0;
}

解法1函数实现:

int numberOf1(int number){
    int counts = 0;
    unsigned int flag = 1;
    while(flag){
        if(number & flag)  //不断和左移后的1做位与操作, 为真(1)便计数
            ++counts;
        flag = flag << 1;   //32位就需要循环32次!!!
    }

    return counts;
}

解法2函数实现:

int NumberOf1(int number){
    int counts = 0;

    while(number){  //原理:将整数每次减一后与原整数做位与操作
        ++counts;
        number = (number - 1) & number; 
    }

    return counts;
}

总结:把一个整数减去1之后再和原来的整数做位与运算,得到的结果相当于是把整数的二进制表示中的最右边一个1变成0。很多二进制的问题都可以用这个思路解决。

相关题目:用一条语句判断一个整数是不是2的整数次方。我们可以将这个整数减1再与原整数做与运算,如果值为0代表是2的整数次方,否则不是。

//判断一个整数是不是2的整数次方
bool numberOfSquare(int num){
    if(!( (num - 1) & num)) //对结果取反
        return true;  //是2的整数次方就返回true
    else
        return false;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值