位运算技巧

位操作介绍

& 与运算

规则:都为 1 时,为 1,否则为 0

例如:
  0 0 1 1
& 0 1 0 1
----------
  0 0 0 1

| 或运算

规则:都为 0 时,为 0,否则为 1

例如:
  0 0 1 1
| 0 1 0 1
----------
  0 1 1 1

^ 异或运算

规则:相同时,为 0,否则为 1

例如:
  0 0 1 1
^ 0 1 0 1
----------
  0 1 1 0

~ 取反运算

规则:0变1,1变0

例如:
~ 0 0 1 1
----------
  1 1 0 0

<< 左移运算

规则:向左进行移位操作,高位丢弃,低位补 0

例如:
a = 8
b = a << 3
移位前(a):0000 0000 0000 0000 0000 0000 0000 1000
移位后(b):0000 0000 0000 0000 0000 0000 0100 0000

>> 右移运算

规则:向右进行移位操作,对无符号数,高位补 0,对于有符号数,高位补符号位

例如:
a = 8
b = a >> 3
移位前(a):0000 0000 0000 0000 0000 0000 0000 1000
移位后(b):0000 0000 0000 0000 0000 0000 0000 0001
​
a = -8
b = a >> 3
移位前(a):1111 1111 1111 1111 1111 1111 1111 1000
移位前(b):1111 1111 1111 1111 1111 1111 1111 1111

位运算技巧

乘除法(整数)

数 a 向右移一位,相当于将 a 除以 2;数 a 向左移一位,相当于将 a 乘以 2

例如:
a = 2
a>>1 ---> 1
a<<1 ---> 4

a = 1
a>>1 ---> 0
a<<1 ---> 2

交换两数

def swap(a,b):
    '''
    常规方法(不需要第三个变量),效率不如位运算高
    '''
    a = a + b
    b = a - b
    a = a- b
    return a,b

def swap(a,b):
    '''
    位运算方法(不需要第三个变量)
    '''
    # 此时a记录a、b不同的位,a ^= b ---> a = (a^b)
    a ^= b
    # b把和a不同的位取反就变为了a,b ^= a ---> b = b^(a^b) ---> b = (b^b)^a = a
    b ^= a
    # a变为b,和上面原理一致,a ^= b ---> a = (a^b)^a = (a^a)^b = b
    a ^= b
    return a,b

判断奇偶数

最后一位是0时是偶数
a = 4
if a & 1 == 0:
    print('偶数')
else:
    print('奇数')

取相反数

def reversal(a):
    '''
    相反数为取反后加一
    '''
    return ~a + 1

取绝对值

def abs(a):
    # 取得符号(正/负),正数时i=0,负数时i=-1
    i = a>>31
    # 加括号是因为-的优先级比^高,a^i表示0时不变,-1时取反,负数时要加一,所以 - i
    return (a^i) - i

统计二进制中1的个数

count = 0
while a:
	# 消除最后一位1
    # a - 1 --> 把当前为1的位变为0,a & (a - 1) --> 把当前为1的位以及后面的所有位都置0
    a = a & (a - 1)
    count += 1

求m的n次方

def pow(m,n):
    '''
    求m的n次方
    例如(3的5次方,5的二进制为0101):
        3^5 = 3^(1 * 2^0 + 0 * 2^1 + 1 * 2^2) = 3^(2^0) * 3^(2^2)
    上述例子若直接循环需要循环5次,用二进制只需循环3次
    '''
    sum = 1
    tem = m
    while n != 0:
        if n&1 == 1:
            sum *= tem
        # 上述例子中tem变化情况: 3^(2^0) --> 3^(2^1) --> 3^(2^2) --> 3^(2^3) --> ...(实际循环到这里就终止了)
        tem *= tem
        n = n>>1
    return sum

找出不大于n的最大的2的幂指数

def findN(n):
    '''
    找出不大于n的最大的2的幂指数
    这里示例的为32位的二进制
    以n = 10000000示例说明
    '''
    # 11000000
    n |= n>>1
    # 11110000
    n |= n>>2
    # 11111111
    n |= n>>4
    # 11111111
    n |= n>>8
    # 11111111
    n |= n>>16
    # 10000000
    return (n+1)>>1

找到二进制中最左边/最右边为1的位

def findLeft(n):
    '''
    找到最左边为1的位
    -n为n取反加1
    '''
    return (-n)&n


def findRight(n):
    '''
    找到最右边为1的位,同找出不大于n的最大的2的幂指数
    这里示例的为32位的二进制
    以n = 10000000示例说明
    '''
    # 11000000
    n |= n >> 1
    # 11110000
    n |= n >> 2
    # 11111111
    n |= n >> 4
    # 11111111
    n |= n >> 8
    # 11111111
    n |= n >> 16
    # 10000000
    return (n + 1) >> 1
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值