位运算
一 基础:位运算符
位运算在刚入门时学起来还是挺难的,不过慢慢来,用多了也就会了
首先要把位运算的基本符号和含义弄清,如下图 咳,懒得打表格,直接从百度找的图
另外,位运算是以二进制数为基础的所以要学位运算,先得学通二进制(我会在之后的某一篇文章里讨论一下二进制)
看完图我们来一 一介绍
1.左移和右移:将一个变量对应的二进制数向左(右)移一位
2.按位与:两个变量对应的二进制数相与,都为1则结果为1,有一个为0则结果为0
常用于将变量中的某一位清零同时保留其他位不变或者获取变量中的某一位
3.按位或:不同于按位与,按位或只要一个为1结果就为1
常用于将变量中的某一位置为一并保留其他位不变
4.按位异或:两个变量对应的二进制数相对应的位上数不相同则结果为1(假设一个数为001,另一个为101,则结果为100)
5.取反:相当于 ‘ !’
二 位运算能干什么?
搞清了基础的位运算符以后,我们就会想到一个很严肃的问题
位运算到底能干嘛?
位运算常用于与二进制相关的题目
不过它也可以用来实现其他的运算
我们看几个例子
1.求平均数
#include<iostream>
using namespace std;
int main(){
int x,y;
cin>>x>>y;
cout<<(x&y)+((x^y)>>1);
return 0;
}
我第一次看到这段代码的时候,一脸蒙蔽,尤其这条语句
cout<<(x&y)+((x^y)>>1);
这什么玩意儿??
所以现在我们来仔细看看这段代码
我们以输入3和5为例
- 将x和y转换为二进制数011和101
- x&y=001&101=001
- x^y=011异或110=110
- (x^y)>>1=110>>1=11
- (x&y)+((x^y)>>1)=001+11=100
- 100对应十进制4
通过这个实例我们可以看出,学会位运算,可以很好地 装逼 解决问题
注意 位运算比四则运算效率更高,可以提高运行速度
接下来我们再看一段代码
2. 交换两数的值
#include<iostream>
using namespace std;
int main(){
int x,y;
cin>>x>>y;
x^=y;
y^=x;
x^=y;
cout<<x<<" "<<y;
return 0;
}
这里我就不解释了,各位自己琢磨一下
3.快速幂
二进制其实也可以用来求a^b
(其实这个是从别人那里学的,大家可以戳这里获取其他求快速幂的方法)
int quickPower(int a, int b)//是求a的b次方
{
int ans = 1, base = a;//ans为答案,base为a^(2^n)
while(b > 0)//b是一个变化的二进制数,如果还没有用完
{
if(b & 1)//&是位运算,b&1表示b在二进制下最后一位是不是1,如果是:
ans *= base;//把ans乘上对应的a^(2^n)
base *= base;//base自乘,由a^(2^n)变成a^(2^(n+1))
b >>= 1;//位运算,b右移一位,如101变成10(把最右边的1移掉了),10010变成1001。现在b在二进制下最后一位是刚刚的倒数第二位
}
return ans;
}
最后贴几个式子
1. x * 10 等价于 (x<<3)+(x<<1)
2. x!=y 等价于 x^y
3. x!=-1 等价于 ~x
4. x * 2 等价于 x<<1
5. x * 2+1 等价于 x<<1|1
6. x/2 等价于 x>>1
7. (x+1)%2 等价于 x^1
8. x%2 等价于 x&1
9. x%2=0 等价于 ~(x&1)
10. 判断奇数偶数x&1 结果为1奇数,否则偶数
想要练习的同学可以 戳这里
这里再分享一篇关于利用位运算做加减法的 戳这里