二进制和位运算

以前对于位运算, 二级制了解的比较少. 这里统一记录一下使用和理解. 主要使用 python 做示范.

2 进制:逢 2 进 1
8 进制:逢 8 进 1
16 进制:逢 16 进 1

在 C 程序中的表示 (python 中也一样):

1
2
3
0b101 /*2进制 0b开头*/
0115   /*8进制 0开头*/
0xFFF  /*16进制 0x开头*/

转换十进制方法: 个位直接加,十位是进制数的 1 次方,百位是进制数的 2 次方,高位以此类推即可
0b101 = 1 + 0*2 + 1*2*2
0115 = 5 + 1*8 + 1*8*8
0xFAF = 15 + 10*15 + 15*15*15

我其实用的不是特别多,见的也不多。但是在很多的官方案例中出现过,比如 python 人脸识别中的跳出循环

1
2
if cv2.waitKey(1) & 0xFF == ord('q'):
    break

先把所有的运算符列出来:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<<  #左移
>>  #右移
|   #位或 
&   #位与
^   #位异或
~   #非

<<  #左移
将所有的0和1的位置进行左移移位之后将空位补0 
左移操作相当于乘以2**n以5 << 3 为例相当于5(2*3),结果为40
0b101 变成了 0b101000
# 一个int是4个字节,一个字节是8位(bit),它存储的大小就是32位
# 如果加了0,超出了32位边界,那么就是溢出了

>>  #右移
将所有的0和1的位置进行右移(直接舍弃)空位正数补0负数补1
右移操作相当于除以2**n8 >> 3 相当于8/(2**3)=1

|   #位或 
0b110 | 0b101   #输出7,即0b111
只要有一位有1就为1可以用在综合条件

&   #位与
0b110 & 0b011   #输出2,即0b010
相同的位才为1可以用在linux权限

^   #位异或
0b1010 ^ 0b1111  #输出5,即0b0101
异或常用于将所有的位反转相同的位置是0否则其他的位置变1

~   #非
~0b101  #输出2,即0b010
这个是单独运算的直接就把所有的反转了
  1. 查看 python 结果
1
2
3
4
5
6
$ python
Python 3.6.3 (default, Oct 16 2017, 17:26:31)
[GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.37)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> print(ord('q'))
113
  1. 查看键盘 q 对应的数字是多少
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#include <stdio.h>

int main()
{
    char i;
    scanf("%c", &i);
    printf("i = %d \n", i);

    return 0;
}
1
2
3
4
5
6
7
Launching: '/Users/user/kent/c/a.out'
Working directory: '/Users/user/kent/c'
1 arguments:
argv[0] = '/Users/user/kent/c/a.out'
q
q = 113 
Process exited with status 0
  1. 那么推算如下
1
2
3
4
5
cv2.waitKey(1) & 0xFF == ord('q')
cv2.waitKey(1) & 0xFF == 113
0xFF代表了你键盘上的所有按键都能匹配到(包括一些系统自己拓展的特殊按键)
当我们按了`q`,cv2.waitKey(1)得到的就是113的二进制和0xFF匹配出来的结果就是二进制的113在任何系统上转换为十进制都会和右边的十进制113相等
避免了bug