什么是位运算?
从现代计算机中所有的数据二进制的形式存储在设备中。即 0、1 两种状态,计算机对二进制数据进行的运算都是叫位运算,也就是将符号位共同参与运算的运算。
位运算符
计算机要进行位运算,那么就一定会用到位运算符,我们先将所有计算机用到的位运算符列出来,然后再去一一讲解这些位运算符的作用是什么。
运算符 | 功能 | 用法 |
---|---|---|
& | 位与 | 运算对象 & 运算对象 |
| | 位或 | 运算对象 | 运算对象 |
^ | 位异或 | 运算对象 ^ 运算对象 |
<< | 左移 | 运算对象<<运算对象 |
>> | 右移 | 运算对象>>运算对象 |
~ | 取反 | ~运算对象 |
位与&,位或|,位异或^操作符。
忽略变量类型,假设a = 8,b = 7 ,它们在计算机上都各自用一个字节去储存自身的值。又因为计算机是用二进制存储数据的,那么a在计算机中的表示值就是0000 1000 ,b就是0000 0111。如下图所示:
a:0000 1000
b:0000 0111
假设列好了,我们下面依次单独讲解一下这3个位操作符。
位与操作符 &
位与操作符,顾名思义,就是两个二进制数的每一位都单独拿出来做 与 操作。我们各位高中的时候都学过一点逻辑运算吧。与 就是都为真才是真,也就是 真真为真 真假为假 假假为假。那在计算机的世界里面,我们人为的把 1 视为真,把 0 视为假。我们假设c = a & b,那么c = 多少呢?
a:0000 0111
b:0000 1000
c:0000 0000
答案是0,因为c的二进制串就是将a与b的二进制串做了位与操作后得到的答案。
int main(){
int a = 7;
int b = 8;
int c = a&b;
cout<<c<<endl;
}
输出结果:0
位或运算符 |
刚刚已经生动形象的讲过了位或运算符的用法,同理,位或运算符也是将每个二进制位做 或操作。或就是两个中只要有一个真就为真,也就是真假为真,真真为真,假假为假。还是那a b c三个数举例子:
a:0000 0111
b:0000 1000
c:0000 1111
c转换为10进制后值为15
位异或操作符
还是同理,位异或操作符,就是将每个二进制位做异或操作。而异或操作是两个钟有且只有一个为真才为真,所以就是真真为假,假假为假,真假为真。拿a、b、c三数举例子:
a:0000 0111
b:0000 1000
c:0000 1111
c转换为10进制数后值为15
异或运算符语言性质: 当一个数与另一个数异或两次时,结果仍然是原来的数
5 ^ 6 = 3;
5 ^ 3 = 6;
6 ^ 3 = 5;
移位操作符
先简单说一下移位运算符的定义:
将运算符左侧的运算对象的每一个二进制位向指定方向移动右侧运算对象值的位数。(<<左移操作符,就像左移动,>>右移操作符就向右移动)
比如如下例子,将10向右移动3位:
首先10可以用二进制表示为:0000 1010
那将10的每一个二进制位都向右移动3位呢?就变成了 0101 0000
看看程序演示:
int main()
{
int a = 10<<3;
cout<<a<<endl;
}
输出结果:
(base) zoom@192 ch01 % g++ test.cpp -std=c++17 -o test.exe && ./test.exe
80
在这里需要注意!🍅
右侧运算负一定不能为负!!!而且值要小于结果的位数,否则会发生未定义的行为。
在这里面移动到边界之外的值就被舍弃掉了,就比如我们将15向右移动3位
int main()
{
int a = 15>>3;
cout<<a<<endl;
}
输出结果:
1
位求反操作符
这个操作符比较简单,它的定义就是:
将运算对象的每一个二进制位都逐位求反后生成一个新值。
话虽什么说,看起来是十分简单好懂了
但是,实际操作起来你可能会觉得有点稍微的不理解,比如:为什么int数5取反后会是-6呢?
int a = 5;
cout<<~a<<endl;
输出结果:
-6
这是因为,int有32bit,所以5在计算机上的表示就是这样:
00000000 00000000 00000000 00000101
注意,左手边第一位叫做符号位,符号位为0时,这个数就是个正数,符号位为1时,这个数就是个负数。
5取反后长这样:
11111111 11111111 11111111 11111010
这一串数字其实就是一个负数的补码,我们把它翻译成原码就可以读出来是几了。
在这里就需要用到原码,反码,补码的知识,如果对于这方面你不知道,OK,那你可以就理解不了为啥 int 数 5 取反后就变成了-6。具体可以看我写的这篇文章:教你清楚理解什么是原码、反码、补码
总结
位运算符作用与整数类型的运算对象,并把运算对象看做是一个二进制位的 集合。位运算符具有检查和设置二进制位的功能。
如果想看位运算符在算法中有什么作用,也可以移步我的这篇文章:面试题 01.01. 判定字符是否唯一。
这篇文章会告诉你我们在算法中该如何使用位运算符。