一些运算规则可以看这篇文章,基础运算为:
& | 与 | 两个位都为1时,结果才为1 |
| | 或 | 两个位都为0时,结果才为0 |
^ | 异或 | 两个位相同为0,相异为1 |
~ | 取反 | 0变1,1变0 |
<< | 左移 | 各二进位全部左移若干位,高位丢弃,低位补0 |
>> | 右移 | 各二进位全部右移若干位,对无符号数,高位补0,有符号数,各编译器处理方法不一样,有的补符号位(算术右移),有的补0(逻辑右移) |
一些总结:1.异或判断数组中的数值是否重复,重复的数值可通过异或删除。
2.位运算交换两整数
a ^= b;
b ^= a;
a ^= b;
3.位运算改变正负性和求绝对值
~ a + 1;
对于正数而言,补码就是原码,所以按位取反再 + 1 +1 +1则得到对应真值负数的补码,而对于负数,其补码进行按位取反再 + 1 +1 +1则得到对应真值正数的补码,变为原码
力扣中有一些题目使用bitset
来运算二进制(把二进制当成一个数组来操纵,另外结合一些二进制的性质),std::bitset
是 C++ 标准库中的一个类,用于表示二进制位序列。它提供了一种方便的方式来处理二进制数据,尤其适用于位运算操作。用法有:
常用函数
size()
返回std::bitset
的长度count()
返回std::bitset
中值为 1 的位的数量any()
返回std::bitset
中是否存在值为 1 的位none()
返回std::bitset
中是否所有位都是 0all()
返回std::bitset
中是否所有位都是 1test(pos)
返回std::bitset
中位于pos
位置的值set(pos)
将std::bitset
中位于pos
位置的值设为 1reset(pos)
将std::bitset
中位于pos
位置的值设为 0flip(pos)
将std::bitset
中位于pos
位置的值取反to_ulong()
返回std::bitset
转换成的无符号整数值to_ullong()
返回std::bitset
转换成的无符号长整数值-
bitset<8>foo(string("10011011")); cout<<foo.count()<<endl;//5 (count函数用来求bitset中1的位数,foo中共有5个1 cout<<foo.size()<<endl;//8 (size函数用来求bitset的大小,一共有8位 cout<<foo.test(0)<< endl;//true (test函数用来查下标处的元素是0还是1,并返回false或true,此处foo[0]为1,返回true cout<<foo.test(2)<<endl;//false (同理,foo[2]为0,返回false cout<<foo.any()<<endl;//true (any函数检查bitset中是否有1 cout<<foo.none()<<endl;//false (none函数检查bitset中是否没有1 cout<<foo.all()<<endl;//false (all函数检查bitset中是全部为1
一:赋值,字符串赋值
bitset<4>a1;//长度为4,默认以0填充
bitset<8>a2;//长度为8,将12以二进制保存,前面用0补充
string s = "100101";
bitset<10>a3(s);//长度为10,前面用0补充
//实验检测,char在普通环境不能直接赋值给bitset
//要开c++11,针不戳
char s2[] = "10101";
bitset<13>a4(s2);//长度为13,前面用0补充
//所以这玩意noip上不能用……
cout<<a1<<endl;//0000
cout<<a2<<endl;//00001100
cout<<a3<<endl;//0000100101
cout<<a4<<endl;//0000000010101
二可以直接进行位运算,就是一个二进制
std::bitset<4> bitset1("1010");
std::bitset<4> bitset2("0110");
std::bitset<4> bitset3 = bitset1 & bitset2; // 按位与运算
std::bitset<4> bitset4 = bitset1 | bitset2; // 按位或运算
std::bitset<4> bitset5 = bitset1 ^ bitset2; // 按位异或运算
std::bitset<4> bitset6 = ~bitset
std::bitset<4> bitset1("0101");
std::bitset<4> bitset2 = bitset1 << 2; // 左移 2 位,结果为 "010100"
std::bitset<4> bitset3 = bitset1 >> 1; // 右移 1 位,结果为 "0010"
显示时可直接转为字符串进行显示
std::bitset<4> bitset1("1010");
std::string str = bitset1.to_string(); // "1010"
。。
例子:下一个数。给定一个正整数,找出与其二进制表达式中1的个数相同且大小最接近的那两个数(一个略大,一个略小)。
(1)找略大的那一个数:
找第一个左边一位为0的1向左交换(01xxx这种形式,01xxx->10xxx),并将位于其右边高位的1全部尽可能后移;
边界应该不能超过2147483647,大于这个则返回-1。
(2)找略小的那一个数:
找第一个右边一位为0的1向右交换(10xxx这种形式,10xxx->01xxx),并将位于其右边低位的1全部尽可能前移;
若数的最高有效位及其右边的数位全为1则不存在更小数,返回-1
vector<int> findClosedNumbers(int num) {
//return {1,1};
vector<int> nums(31,0);
for(int i=0;i<=30;++i){
nums[i]=pow(2,i);
}//预处理一个数组,{1,2,4,8,16...}某一位为1,nums[i]^INT_MAX可以将num[i]取反,即0000 ... 0001转化为1111 ... 1110
vector<int> res(2,-1);
int flag1=1,flag0=1;
for(int i=0;i<30;++i){
if((nums[i]&num)==0&&flag1&&nums[i+1]&num) {
//遇到了第一个10
res[1]=num-nums[i+1]+nums[i];
flag1=0;
int k=-1,l=i;//k记录从最右边开始未处理的1,l处理10转化为01后的0
while(l&&(nums[l-1]&num)==0&&nums[k+1]&num){//处理类似1001,10011这种情况(转化完应为0110,01110)
res[1]=res[1]-nums[++k]+nums[--l];
if(l==0) break;
}
}
if((nums[i]&num)&&flag0&&(nums[i+1]&num)==0){
//遇到了第一个01
res[0]=num-nums[i]+nums[i+1];
flag0=0;
int k=-1,l=i;//k记录从最右边开始未处理的0,l处理01转化为10后的1
while(l&&nums[l-1]&num&&(nums[k+1]&num)==0){//处理类似1111000,1111100这种情况(转化完应为10000111,10001111)
res[0]=res[0]+nums[++k]-nums[--l];
if(l==0) break;
}
}
}
return res;
给定两个整型数字 N
与 M
,以及表示比特位置的 i
与 j
(i <= j
,且从 0 位开始计算)。
编写一种方法,使 M
对应的二进制数字插入 N
对应的二进制数字的第 i ~ j
位区域,不足之处用 0
补齐
//int转bit,bit做运算,先补位后移动
int insertBits(int N, int M, int i, int j) {
for (int k = i; k <= j; ++ k)
{ //举例说明: (1 << 3) 表示 00001000,取反后得 11110111
// N &= (11110111) 表示将 N 的第3位置零了
N &= ~(1 << k);//要插入的部分置0
}
return N + (M << i);
int 类型的数temp中有几个1
int count = 0;
while (temp != 0) {
temp &= (temp - 1); // 去掉二进制表示的最右边的1
count++;
}
return count;
int t=0b01010101010101010101010101010101;以二进制的方式定义整数
后面的数是二进制数。