神奇的位运算

1. 不用临时变量交换两个数

异或运算

  • 两个相同的数异或为0 即n ^ n = 0;
  • 任何数与0异或为它本身,即n ^ 0 = n。
  • 支持交换律、结合律
a = a ^ b	# (1)
b = a ^ b	# (2)
a = a ^ b	# (3)

解释如下:

把(1)中的 a 带入(2)中,则有

b = a ^ b = (a ^ b) ^ b = a ^ (b ^ b) = a ^ 0 = a

同理将(1)、(2)的结果带入(3)中,则有

a = a ^ b = (a ^ b) ^ a = (a ^ a) ^ b = 0 ^ b = b

2. 判断一个数的奇偶性

与运算

  • 相同为0,不同为1

判断一个数n是偶数还是奇数,只需要判断n的二进制最后一位是1还是0。是0表示是偶数,是1表示是奇数。

if n & 1 == 1: # n为奇数

3. 乘2/除2

n << 1	# 左移一位,表示乘2
n >> 1 	# 右移一位,表示除2

4. 取两个数中的最大值

def max(a, b):
    return b & ((a-b) >> 31) | a & (~(a-b) >> 31)

解释如下:

  1. b & ((a-b) >> 31)其中(a-b) >> 31 表示取(a-b)的符号位。

b <= a时,符号位为0,b & 0 = 0

b > a时,符号位为-1。b & -1 = b

即当b > a时结果为b,否则结果为0。

  1. a & (~(a-b) >> 31)其中(~(a-b) >> 31) 表示对(a-b)的符号位取反

a >= b时,取反结果为-1,a & -1 = a

a < b时,取反结果为0,a & 0 = 0

即当a >= b时结果为a,否则结果为0。

  1. 最后对前两步结果进行运算,因为前两步的结果中一定有一个为0,另一个非0(即最大值)。所以经过运算后结果非0(即为最大值)。

5. 取两个数中的最小值

def max(a, b):
    return a & ((a-b) >> 31) | b & (~(a-b) >> 31)

6. 取绝对值

def abs(n):
    return (n ^ (n >> 31) - (n >> 31))

7. 找出只出现一次的数字

在一组整型数据中,只有一个数字出现了一次,其余数字都出现了两次。找出那个只出现一次的数字。

由异或运算的特性可知:两个相同数字进行异或结果为0;一个数和0异或结果为它本身;且异或支持交换律和结合律。所以只需要对全部的数字进行异或运算,结果就是只出现一次的数字。如l = [1,2,1,0,0]

1 ^ 2 ^ 1 ^ 0 ^ 0 = (1 ^ 1) ^ (0 ^ 0) ^ 2 = 0 ^ 0 ^ 2 = 2

def find_only(l):
    tmp = l[0]
    for i in range(1, len(l)-1):
        tmp ^= l[i]
    return tmp

l = [1,2,3,4,4,3,1,0,0]
posted @ 2019-12-29 12:51  西加加先生  阅读(199)  评论(0编辑  收藏  举报