C/C++常见的位操作

常见的位操作

循环左移两位 : (a >> (N - 2) | a << 2)
循环右移两位 : (a << (N - 2) | a >> 2)
判断奇数 : (x&1)==1
判断偶数 : (x&1)==0
二进制数字尾部第一个1所处的位置: x & -x
二进制数字表示包含几个1:n-1 & n

&|^~>><<
逻辑与运算逻辑或运算异或运算非运算右移运算左移运算

利用位运算来表示集合运算

可以利用二进制来表示{0,1,2,3,…,n - 1}的子集S;从右往左第i位(各位从0开始编号)表示元素i是否在集合S中,下展示了二进制0100011000110111是如何表示{0,1,2,4,5,9,10,14}的

0100011000110111
1514131211109876543210

位运算与集合运算的对应关系

 ABA & BA | BA ^ B
二进制1011001100001001111011010
集合{1,2,4}{2,3}{2}{1,2,3,4}{1,3,4}

注:
A&B、A|B、A^B分别对应集合的交,并,对称差运算。
空集{Ø}表示为0
全集{0,1,2,3,…,n - 1}对应的值定义为All_bits = (1<<n) - 1;
如果A对应的全集为All_bits,则A的补集为A ^ All_bits;


利用位运算表示加法操作

解题趣谈

本人在leetcode上刷题遇到了这个有趣的题目
Sum of Two Integers

int getSum(int a, int b) {
    long long carry; // 64-bit
    while (b != 0) {
    //b在第2轮循环之后都是作为进位出现的。如果进位为0,代表循环结束
        carry = a & b;//可以对比真值表观察到:carry恰好代表了进位。只不过进位的位置在原本应该在的位置的后一位
        a = a ^ b;//模拟无进位的加法运算[可以对比真值表]
        b = ((carry & 0xffffffff) << 1); //将carry限制在32bit之内。防止溢出。
        //将carry左移一位是为了将进位放在正确的位置上面
    }
    return a;
}
  • 通过真值表可以发现carry=a & b 和不带进位的sum = a ^ b
xyx & yx ^ y
0000
0101
1001
1110

模拟全加器的加减乘除运算

计算机加法的实现

半加器真值表

xysumcarry
0000
0110
1010
1101

由此可以看出来:
半加器中sum = a + b对应于a ^ b
半加器中carry(a + b的进位)对应于a & b

在半加器的基础上实现多位全加器

xyicarry(低位进位)sumcarry
00000
00110
01010
01101
10010
10101
11001
11111

对比真值表可以发现:

sum = x ^ y ^ icarry

carry = (x & y) | (x & icarry) | (y & icarry)

计算机减法的实现

减法实质上是一个数加上另一个数的相反数
因此实现减法,只要对减数求2-补码(取反加一),然后跟被减数相加即可得到差值
也就是说:

b = getsum(~b,1)//getsum的具体实现过程前面[解题趣谈]有,本节不再赘述。
sum = getsum(a,b)

计算机乘法和除法的实现

位运算的相关应用

请务必注意

以后遇到关于2的题或者是真假的题,一定要敏感啊,想到二进制

1.判断是否是2的幂

思路分析:
2的整数次方对应的二进制的最高位上只有一个1,那么将该数字减去1再与该数字进行与运算,如果是2的整数次方,那么结果一定为0

if(n & (n - 1) == 0){ 
    printf("是偶数!\n");
}

1.2判断是否是4的幂(上题的变种形式)

题目描述:
Power of Four
思路描述:
请注意:如果一个数是4的幂,那么必然是最高为是1,后面跟着偶数个0
首先如果一个数是4的幂,那么必然满足2的幂的条件。那么这个数只有最高位是1
其次再与0x55555555,如果该数的最高位的1出现在奇数位上。(在这里我们设定0x55555555下标从1开始,而不是从0开始,也就是从1…32位)

bool isPowerOfFour(int num) {
        if(num < 0) return false;
        if ( num & (num - 1) )         //判断x是否为2的幂次方
             return false;
        return num & 0x55555555; //判断1是不是出现在奇数位上
    }

2.判断奇数偶数

//比较常用的一个小知识点
if((i&1) == 0){//这个只是一个小技巧,因为位运算的速度远远超过其余运算
    cout<<"偶数"<<endl;
}else{
    cout<<"奇数"<<endl;
}

3.计算二进制数字从尾部开始连续1的数目

int v;
int count = 0;  // count用来保存计算的结果
while(v & 1){
   v = v >> 1;
   count ++;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值