zoukankan      html  css  js  c++  java
  • 神奇的位运算

    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]
    
  • 相关阅读:
    前端开发小结(持续更新)
    UDP 通讯及内部分析(合集)
    困扰我三天的问题
    Clang Format Style Options (.clang-format 配置文件文档)
    关于共享库的那些事儿
    如何在VMWare的NAT模式下使用traceroute(解析vmnat的行为)
    Linux网络配置
    Ansible Ad-Hoc命令集
    Ansible基础使用
    Ansible部署及配置介绍
  • 原文地址:https://www.cnblogs.com/ghostlee/p/12114706.html
Copyright © 2011-2022 走看看