位运算符在我们实际项目的应用可能比较少,久而久之可能就忘什么是按位运算符?今天刚好遇到关于按运算的实际应用。为了方便以后查询及加深自己对位运算符的理解,特此记录相关的知识点。我们首先回顾一下什么是按位运算符?
位运算:我们都知道计算存储数值是二进制表示的。位运算就是直接对二进制进行运算。主要分为 与“$”, 或"|",非“~”和或异“^”运算符

  1. 与运算符($)
    0&0=0,0&1=0,1&0=0,1&1=1
  2. 或运算符(|)
    0&0=0,0&1=1,1&0=1,1&1=1
  3. 非(~)运算
    取反。0->1,1->0. a=0111, ~a = 1000
  4. 异或(^)运算
    同为假,异为真 所以它是这样的算法: 0&0=0,0&1=1,1&0=1,1&1=0
  5. << 左移运算符
    1 << 3
  6. ">>"右移运算符
    1 >> 3

应用

  1. 设置flags
#define XT_FIND_BOND (1 << 4)
#define XT_FIND_SSSR (1 << 5)

#define SET_OR_UNSET_FLAG(X) \
     if(value) setFlag(X);
	 else unsetFlag(X);

class Mol
{
private:
	unsigned int _flags;
	void setFlag(int flag) {_flags |= flag;}
	void unsetFlag(int flag) { _flags &= (~(flag));}
	bool hasFlag(int flag) {return  (_flags & flag)!=0;}
	
public:
	Mol():_flags(0){}
	void setSSSRFlag(bool value=true){SET_OR_UNSET_FLAG(XT_FIND_SSSR)} //设置 SSSR 标签
	bool isSetSSSRFlag() const {return hasFlag(XT_FIND_SSSR);} 

}

基于位运算符操作,我们可以高效地为Mol设置各种flag。

2 . 从整数中寻找出现一次的数

    int x[] = {1, 3, 1, 3, 4, 5};
    int res = 0;
    for (int i:x) {
        res ^= i;
    }
	
// 寻找整数中恰好只有一个整数出现2次的数
    int x1[] = {1, 2, 3, 4, 5, 6,2};
    int res1 = 0;
    int i = 1;
    int n = sizeof(x1) / sizeof(int);

    while (i < n) {
        res1 ^= i;
        res1 ^= x1[i];
        i++;
    }
    res1 ^= x1[0];