01、目录
目录
- 01、目录
- 02、前言
- 03、初识位运算
- 04、位运算操作符
- 4.1 按位与
- 4.2 按位或
- 4.3 按位异或
- 4.4 按位取反
- 4.5 左移
- 4.6 右移
- 05、总结
02、前言
今天恰逢Visual Studio 2015出了点毛病,迫于无奈之下只有卸载重装,这种比较费时间的事情,就写一篇博客叭。
整理了下思路,复习了下位运算,今天就简单聊聊它。
虽然位运算很底层,一听人说直接操作二进制,哇,这么高大上。其实,搞明白了也没啥,而且位运算的只是真的不多。我下面就直接开始吧。
03、初识位运算
其实只要了解计算机的人都或多或少知道,计算机的各种操作都是通过0和1来完成的。
没错,计算机操作的本质就是操作二进制。
而我们程序员是不可能盯着密密麻麻的二进制来编写程序的,就算你厉害,看得懂,那也不可能。
大众化的才能被人们广泛接受。
所以,某某某就通过出于这个需求的考虑,设计了一种操作二进制的规则,也就是位运算。
先来篇口诀吧!
清零取反要用与,某位置一可用或
若要取反和交换,轻轻松松用异或
再列举下多种语言的位运算:
含义 | pascal | C/C++ | java |
---|---|---|---|
按位与 | a and b | a & b | a & b |
按位或 | a or b | a | b |
按位异或 | a xor b | a ^ b | a ^ b |
按位取反 | not a | ~a | ~a |
左移 | a shl b | a << b | a << b |
有符号右移 | a shr b | a >> b | a >> b |
无符号右移 | / | / | a >>> b |
这里的pascal也是一种语言,点击此处 了解!
介绍了位运算,就继续介绍这些符号怎么用,可以达到什么效果吧!
04、位运算操作符
这里其他两种语言我不做介绍,除了第一种,Java与C/C++基本一样。
主要介绍C/C++中的位运算:
4.1 按位与
按位与,在C++中表示为 &
位运算其实只有一种情况,用竖式两位对齐计算,下面是运算结果:
代码中的例子,我写一次,后面与之大同小异。
//比如:0按位与0
int a = 0 & 0;
printf("a= %d\n",a); //result:0
0 & 0 = 0
0 & 1 = 0
1 & 0 = 0
1 & 1 = 1
也就是说,只有两者都为1,结果才是1,其余都是0 ——>按位与
简记:按位与,有零则零!
4.2 按位或
按位或,在C++中表示为 |
四种情况如下:
0 | 0 = 0
0 | 1 = 1
1 | 0 = 1
1 | 1 = 1
也就是说,只有两个都为0时,结果才为0,其余都是1——>按位或
简记:按位或,有壹则壹!
4.3 按位异或
按位异或,在C++中为 ^ (这里初学者容易搞成乘方,注意哈!)
四种情况如下:
0 ^ 0 = 0
0 ^ 1 = 1
1 ^ 0 = 1
1 ^ 1 = 0
按位与或的情况很特殊,很容易迷惑人,这跟乘方实在太像了,不过这里我们还是总结下:相同是0,不同则是1——>按位与或
简记:同零异壹!
4.4 按位取反
按位取反,在C++中为 ~
这里情况分两种:
~0 = 1
~1 = 0
用得不多,理解就好,其实我看见有一篇博客讨论按位取反的时候讨论了一下大于0,小于0的情况,这里我说说我的理解,完全没必要,既然位运算的对象是二进制,就只有0和1,没必要脱离主题。
按位取反,我觉得是最好记的,相反就ok,如果是1,则按位取反为0,若是0,则按位取反为1——>按位取反
简记:本身取反!(真假相反)
4.5 左移
左移,在C++中为 <<
不知道怎么表达,先看例子叭!
比如: 8 左移 3bit(位)
//首先8转换为2进制
0000 1000
8 << 3; //整体向左移动3位
0100 0000 //当然这里我的写法优化了下,原型如下:
000 0100 0000 //为使形式好看点,所以上面做了写法优化,右移大同小异,下面不多写
当然这是二进制表示,如果要用数学表示出来即是:
a == 8
n == 2
a << n === a * 2^n 这里的^不是按位与或,而是乘方
记住:左移多少位,右边补多少位,填充数为0即可。
4.6 右移
右移,在C++中为 >>
将操作数的所有位向右平移指定的位数。向右移动了几位,左面补几个 0,向右位移的部分舍弃。
比如 6 右移 1 位
0000 0110 >> 1
结果为:0000 0011
右移n位相当于除以2的n次方
当然我没有提符号右移与无符号右移。那是涉及到负数哈。
其实也是一样的。符号位为最高位,比如:
-10怎么表示:
1000 1010 这就是-10的二进制表示。最高位即,最左边位为1,就是负数,为0就是正数。
学过补码都都应该懂这句话的意思。
补码>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>看这里 补码百科
而负数跟有符号和无符号怎么回事呢?
就是有符号,符号位你右移不能消掉。懂吧,左移跟正数一样。考虑一下这种情况就是上面提到的,我这里提一下规则,举个例子。
- 负数的右移:负数右移的话,由于要保持它是负数,所以负数的二进制的右边补1。如果一直右移的话,最后就就变成0xFFFFFFFF 即-1
如: -4>>1 为-2 ;-4>>2为-1 - 负数的左移:跟正整数左移一样,右边补0,一直左移的话,最后就是0啦。-2<<2 为-4 ; -2<<31为0
05、总结
关于位运算,其实要想搞得很清楚,建议还是搞一下计算机的补码、反码、原码。
值得一提的是:计算机始终是保存的补码。
然后后面如果有时间,我会抽空聊聊这些基础,当然,这在计算机结构专栏里面,我会详细说明。