一、按位运算符
1. 移位运算符
value<<shift//向左移动
value>>shift//向右移动
value是被操作的整数值,shift是要移动的位数
举个栗子:
int 13<<3
int 13>>3
注:
- 腾出的位置用0填充,超出边界的位置被丢弃
- 每一位是前一位的2倍,因此每左移一位相当于乘2,左移n位相当于乘2^n
- C++左移运算符生成一个新值,不修改原来的值
2. 逻辑按位运算符
①位非运算符(~),将每一位转化为它的反面(1转化而为0,0转化为1)
②OR(|),被操作的两个值得对应位至少有一个1,则新值为1,否则为0
③AND(&),被操作的两个值对应位都为1,则新值为1,否则为0
④XOR(^),一个为1,一个为0则新值为1,否则为0
注:
- 这里的位均对于二进制数来说的
二、按位运算符实现二进制和十进制转换
对于一个以1和0组成数组,可以看做二进制数,继而可以表示成十进制整数
那如何将一个十进制数,填加到一个数组中呢:这里需要用到按位运算符
举个栗子:
将20转化为二进制数,并存放在数组中
三、二进制的枚举
1. 枚举集合{0,1,2,……,n-1}
假设有4个商品,每个商品有挑选或者不挑选两种选择,我们用1表示选择,0表示不选择
如图对应其中一种方案:
那么,如何枚举一个出所有方案呢:
我们假设这是二进制数,那么这个二进制数最大为1111不超过1<<5或2^5,于是不断缩小这个数就可以列举出所有的方案
#include"iostream"
#include"stdlib.h"
using namespace std;
int main() {
int x[4];
for (int i = 0; i < 1 << 4; i++) {
memset(x, 0, sizeof(x));
for (int j = 0; j < 4; j++) {
x[j] = i >> j & 1;
cout << x[j];
}
cout << endl;
}
system("pause");
}
程序结果:
注:
- 此种方法只是相对于多重循环来说,更方便,但依然是采用枚举的方式,因此只适用于枚举方案较少的情况
2.枚举集合的子集
假设一个 集合sup:01101,这里要将01100或00100等子集sub枚举出来,这里不能像上面那样将sup-1直到0全部枚举出来,因为有的集合并不是sup的子集。
例如:
01011=01101-2 但01001并不是01101的子集
解决方法: 将sub&sup
这里01011&01101=01001,01001就是sup的子集了
因 为 &保证了sup不为0的地方在sub中也不会为0