位运算相关知识

位运算可以直接操作计算机内存中的整数的二进制位,位运算包括按位取反,按位与,按位或,按位异或,按位左移,按位右移六种运算。计算机在运算的时候是以补码进行运算的,所以运算会把符号也一并运算。
按位取反(~a) 把一个数的二进制位取反,0变成1,1变成0,如果是有符号的数据符号也会一并取反
按位与(a & b) 按位相与。包括符号。按位与的应用:
1 判断奇数偶数:奇数和1与1,偶数和1与是0
按位或(a | b) 按位或的常见应用是二进制特定位上的无条件赋值,例如要把一个数的末尾变成1,就是与1按位或,如果要把一个数的末尾变成0就与1按位或之后在加一。就是将这个数变成和该数最相近的偶数。

按位异或(a ^ b) 这个运算可以用来加密,因为(a ^ b) ^ b = a。因此也可以用来交换两个数:

int main (int a, int b) {
a = a ^ b;
b = a ^ b;
a = a ^ b;
}
与1异或可以翻转特定位的值,与0异或可以保留原值。
按位左移:左移一位相当于乘以2
右移一位相当于除以2。
位运算的一些应用:
1 二进制中1有偶数个还是奇数个

简单粗暴的做法:

#include <iostream>
#include <stdio.h>
using namespace std;

int main() {
    int a = 1314520;
    int b = 1;
    int c = 0;
    for (int i = 0;i < 32;i++) {
        if (a & b) {
            c++;
        }
        b <<= 1;
    }
    cout << c <<endl;
}
但是这样纯粹就是靠计数,通过x - 1将x的二进制最后一位变成0。代码如下:

#include <iostream>
#include <stdio.h>
using namespace std;

int main() {
    int a = 1314520;
    int c = 0;
    while (a) {
        c++;
        a &= (a - 1);
    }
    cout << c << endl;
}
但是为什么这样呢?我们可以假设a的最后一位为1,那么a - 1的最后一位为0,相与之后a的最后一位为0。假设a的二进制的最后一个1是第m位,假设a一共有n位那么那么a - 1 = a[n ... m + 1] 0 11 ... 1
这样a & (a - 1)相当于把a的最后一位1抵消了。
如此往复,当抵消到最后一位1时,a & a - 1 = 0。所以a & a - 1可以消除a的最右边的1。
2 二分查找32位整数的前导0个数
第一种简单粗暴的解法:

#include <iostream>
#include <stdio.h>
using namespace std;

int main() {
    int a = 1;
    int i = 0;
    for (i = 0;i < 31;i++) {
        a = a >> 1;
        if (a == 0) {
            break;
        }
    }
    cout << 31 - i << endl;
}
向右移位是判断有几位非0。因此可以使用二分法

#include <iostream>
#include <stdio.h>
using namespace std;

int main() {
    int a = 4;
    int c = 0;
    int m = 16;
    int cnt = 16;
    while (m < 31) {
        if (a >> m == 0) {
            c += cnt;
            a <<= cnt;
        }
        cnt /= 2;
        m += cnt;

    }
    c -= (a >> 31);
    cout << c << endl;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值