位运算技巧总结

基本运算性质

自身运算

a & a = a
a | a = a
a ^ a = 0

与0运算

a & 0 = 0
a | 0 = a
a ^ 0 = a

与全1运算

a & (~0) = a
a | (~0) = ~0
a ^ (~0) = ~a

与或异或运算率

交换律

a | b = b | a
a & b = b & a
a ^ b = b ^ a

结合律

单个运算符内部满足结合率
(a | b) | c = a | (b | c)
(a & b) & c = a & (b & c)
(a ^ b) ^ c = a ^ (b ^ c)
运算符交叉不满足结合律。
例如(a & b) | c ≠ a & (b | c)

分配律

与运算和或运算满足分配律
(a & b) | c = (a | c) & (b | c)
(a | b) & c = (a & c) | (b & c)
有异或运算的部分不满足
(a ^ b) & c = (a & c) ^ (b & c)
(a & b) ^ c (a ^ c) & (b ^ c)
(a | b) ^ c (a ^ c) | (b ^ c)
(a ^ b) | c (a | c) ^ (b | c)

简单的求证代码

#include <stdio.h>
#include <windows.h>
#include<iostream>
using namespace std;
int main()
{
    std::cout << std::boolalpha;
    for(int i=0;i<100;i++){
        int a=rand(),b=rand(),c=rand();
        int cal1=(a^b)|c;
        //int cal2=a&(b|c);
        int cal2=(a|c)^(b|c);
        cout<<"a:"<<a<<" "<<"b:"<<b<<" "<<"c:"<<c<<" "<<endl<<"cal1:"<<cal1<<" "<<"cal2:"<<cal2<<" "<<"euqal:"<<(cal1==cal2)<<endl;
    }
    //cout<<((1<<31)-1)<<endl<<(1<<31)<<endl;
    system("pause");
    return 0;
}

优先级

位运算优先级比较低,所以一定要加括号
优先级

技巧

异或取反

//全1异或取反
a ^ (~0) = ~a
//i+1位取反
a ^ (1<<i)

取int极大极小值

1、int最大值 (1<<31)-1
2、int最小值 1<<31

取负

-a = ~a + 1

原地交换操作

a ^= b;
b ^= a;
a ^= b;

判断奇偶

a & 1

比较

a^b==0

判断符号是否相同

a ^ b >= 0

第i+1位操作

//取出第i+1位
a & (1<<i)
//i+1位 置1
a |=1<<i
//i+1位 置0
a &=~(1<<i)
//i+1位 反转
a ^ (1<<i)

异或去重

a ^ a = 0
//出现偶数次的即可消去

异或可逆

leetcode 1720

//推导
a^b=c  ---->   a=c^b  b=c^a
a^b^b=c^b
a^0=c^b
a=c^b

删除最末尾的1个1,用于统计1的个数

leetcode 191

a & (a-1)

仅保留最后一个1

a & (-a)
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值