python位运算(一)概述
一、位运算概念
位运算是直接对整数在二进制中进行操作。另我们的电脑电路设计都是基于二进制的,所以在二进制层面效率很高。通常位运算多用在对程序效率要求很高的场景。以下的二进制都以8位为例。第1位是符号位,后面7位是数字位。符号位用0代表非负数,用1代表负数。
二、2进制编码
1、原码
原码是二进制的一种表现方式。取该整数的绝对值的二进制,再加上符号位。该原码只是为了让我们看二进制更直观,直接看出正负数和比较大小。但原码不是计算机保存的二进制,所以不能直接参与计算。如下:
2、反码
反码主要是针对负数的处理。在原码的基础上,符号位不变,其他数值位取反,即把1变成0,把0变成1。反码是为了在计算机中存储二进制,但非真正的二进制值,所以也不直接参与计算。
3、补码
补码是真正的二进制值了,主要也是针对负数。非负数不变,而负数是在反码的基础上加1。如下:
总结如下:
1、正数的二进制值,原码、补码、反码都是一样的;
2、负数的二进制值是其补码,即反码加1。
三、位运算
运算符 | 含义 | 功能 |
---|---|---|
& | 按位与 | 如果两个相应的二进制位都为1,则该位的结果值为1;否则为0。 |
| | 按位或 | 两个相应的二进制位中只要有一个为1,该位的结果值为1。 |
∧ | 按位异或 | 若参加运算的两个二进制位同号则结果为0(假)异号则结果为1(真) |
~ | 取反 | ~是一个单目(元)运算符,用来对一个二进制数按位取反,即将0变1,将1变0。 |
左移 | 左移运算符是用来将一个数的各二进制位全部左移N位,右补0。 | |
>> | 右移 | 表示将a的各二进制位右移N位,移到右端的低位被舍弃,对无符号数,高位补0。 |
1、按位与(&)
按位与,即按照对应位置的二进制and比较。可以把1当作true,把0当作false。1 and 1 = 1,1 and 0 = 0,0 and 1 = 0,0 and 0 = 0,如下示意图:
5&1结果为1。那这个有什么用呢?举个例子:判断数字是奇数还是偶数。普通判断方法求数字除以2求余。传统做法如下:
n%2 0 #True为偶数,False为奇数
可以用按位与运算判断奇偶,运算效率要高很多:
n&1 1 #按位于运算奇数返回1,偶数返回0
2、按位或(|)
按位或,即安装对应位置的二进制or比较。1 or 1 = 1,1 or 0 = 1,0 or 1 = 1,0 or 0 = 0。如:
5|3结果为7。我们可以利用这个方法对数值修正,例如取每个整数向上取奇数。若在这个基础上减1,可以得到向下取偶数。
1>>> map(lambda x:(x|1)-1, range(6))
2[0, 0, 2, 2, 4, 4]
3>>> map(lambda x:x|1, range(6))
4[1, 1, 3, 3, 5, 5]
3、按位异或(^)
按位异或,则是按照对应位置的二进制xor比较。1 xor 1 = 0,1 xor 0 = 1,0 xor 1 = 1,0 xor 0 = 0。例如:
5^3结果为6。出一道算法题目:已知一个数字数组。其中只有一个数字只出现1次,其他数字都出现2次。求只出现1次的数字。利用reduce函数,一句话代码搞定且效率很高。
1def get_one(nums):
2 return reduce(lambda x,y: x^y, nums)
3nums=[1,1,3,2,4,3,4]
4get_one(nums)
4、按位翻转(~)
按位翻转,即不管符号位还是数值位,全部取反码。即1变成0,0变成1。翻转和按位异或有关系,翻转相当于和-1按位异或:~n = n^-1。
这个也可以用于加解密运算。
5、左移运算(<<)
左移运算是将二进制数值整体向左边移动n个位置,空出来的位置补0。例如5<<2:
左移两位,数字5变成20,多了4倍。而从二进制看多了100倍。十进制的4等于二进制的100。这么看来左移运算可以用于乘法计算。
6、右移运算(>>)
右移运算是将二进制数值整体向右边移动n个位置,空出来的位置补上符号位的数值。即正数补0,负数补1。这个右移运算可以类似上面左移运算用于乘法一样,用于除法。这个你可以自己尝试一下。右移了两位相当于101B除以100B,二进制100B对应十进制是3。可以发现该除法计算是取结果的整数部分,5/3 = 1:
捐赠本站(Donate)
如您感觉文章有用,可扫码捐赠本站!(If the article useful, you can scan the QR code to donate))
- Author: shisekong
- Link: https://blog.361way.com/bitwise-operators/5778.html
- License: This work is under a 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议. Kindly fulfill the requirements of the aforementioned License when adapting or creating a derivative of this work.