位操作

位操作

Bit Operation
一、按位操作是在单个字节的层面上对一个或多个位模式或二进制数字符号进行
的操作。处理器支持这种快速简单的操作,而且可以用来比较和计算数值。
l按位操作比除法快得多,是乘法的几倍速度,有时候也比加法快得多。
 
二、基本技巧
1.XOR
— myBits ^ 0 : 不变
— myBits ^ 1 : 翻转
ž 2.左移位相当于乘以2的指数
— x << n = x * (1 << n)
— 8 << 2 = 8 * (1 << 2) = 32
ž 3.按位右移相当于一个除以2的指数
— 00011001 >> 2 = 00000110
— 00011001 >> 4 = 00000001
三、位操作
1、Set Bit
def setBit(a, n):
    return a | (1<<n)

2、Clear Bit

def clearBit(a, n):
    return a & (~(1<<n))

3.Toggle Bit

def toggleBit(a, n):
    return a ^ (1<<n)

4.Test Bit

def testBit(a, n):
    result = a & (1<<n)
    return result != 0

5.将整数转换为Bits(二进制)   此处只考虑了正数

def toBinary(n):
    sb = []
    if n < 256:
        upper = 128
    else:
        upper = 32768
    i = upper
    while i > 0:
        if n & i != 0:
            sb.append(str(1))
        else:
            sb.append(str(0))
        i = i >> 1
    return ''.join(sb)

6.将Bits(二进制)转换为整数  此处只考虑了正数

def convertBits2Int(binary):
    length = len(binary)
    result = 0
    if length > 16:
        raise ValueError("Only Supports 16 Bits")
    for i in range(length):
        c = int(binary[i])
        if (c != 0 and c != 1):
            raise ValueError("binary can only be 0 or 1")
        #result += c << (length - i - 1)
        result = (result << 1) + c
        
    return result

7.用Bits展示小数。

— 给定一个数(十进制小数,如3.72),用字符串将这个数传入,打印它的二进制表示。如果这
个数不能表示为二进制,打印‘ERROR’。
def convertDecimal(f):
    str_f = str(f).split(".")
    int_part, dec_part = divmod(f, 1)
    int_part = int(int_part)
    print(int_part, dec_part)
    
    int_s = ""
    while (int_part > 0):
        r = int_part % 2
        int_part >>= 1
        int_s = str(r) + int_s

    dec_s = [] 
    while (dec_part > 0):
        if (len(dec_s) > 32):
            print("".join(dec_s))
            raise ValueError("Not Support")
        if (dec_part == 1):
            dec_s.append(str(dec_part))
            break
        r = dec_part * 2
        
        if (r >= 1):
            dec_s.append("1")
            dec_part = r - 1
        else:
            dec_s.append("0")
            dec_part = r
        
    return int_s + "." + "".join(dec_s)

8.将HEX转换为整数

def hex2int(s):
    digits = "0123456789ABCDEF"
    val = 0
    for i in range(len(s)):
        c = s[i].upper()
        d = digits.index(c)
        val = 16 * val + d
    return val

9.将整数转换为HEX

def int2hex(d):
    digits = "0123456789ABCDEF"
    if d == 0:
        return "0"
    hex = ""
    while (d > 0):
        digit = d % 16
        hex = digits[digit] + hex
        d = d // 16
    return hex
10.计算一个整数(二进制表示)包含的1的个数
方法一: O(N)
def bitCountA(n):
    count = 0
    while (n != 0):
        if (n & 1 != 0):
            count += 1
        n = n>>1
    return count

方法二:O(k)    (n & (n – 1) == 0)可以检测的是末位是否为1

def bitCountB(n):
    count = 0
    while (n != 0):
        n = n & (n - 1)
        count += 1
    return count

11.下一个2的幂数

— 给定一个整数n, 找到下一个数(这个数比n大,且是2的幂数)
def next2Power(n):
    while (n & (n-1) != 0):
        n = n & (n-1)
    return n << 1

12.检测两个整数的是否有相反符号

— 给定两个整数,检查他们是否有相反的符号
def isOppositeSigns(a, b):
    return (a^b) < 0

13.判断符号

def isPositiveInteger(n):
    return (n >> 31) == 0

14.不使用分支计算一个整数的绝对值

def absoluteA(a):
    mask = a >> 31
    result = (a + mask) ^ mask
    return result

法二:

def absoluteB(a):
    mask = a >> 31
    result = (a ^ mask) - mask
    return result

15.就地(in-place)整数交换

def swap2(a, b):
    a = b - a
    b = b - a
    a = a + b
    print(a, b)

法二:

def swap3(a, b):
    a = a ^ b
    b = a ^ b
    a = a ^ b
    print(a, b)

16.将整数A转换为整数B

— 计算将整数A转换为整数B所需要的位数
def convertA2B(a, b):
    count = 0
    c = a ^ b
    while (c != 0):
        c = c & (c - 1)
        count += 1
    return count

17.Amazing Mask

— 给定两个32-bit的数,N和M,以及两个比特位置 i 和 j 。写一个方法,这个方法可
以将N的i到j之间的值设置为M(即,M变成N的i到j之间的一个子串)
def amazingMask(n, m, i, j):
    allOne = ~0
    left = allOne - ((1<<(j+1))-1)
    right = (1<<i)-1
    mask = left | right

    return (n & mask) | (m << i)

18.不使用算术运算符进行添加

— 写一个两数相加的函数。不可以使用+或者任何算术运算符。
def add(a, b):
    if b == 0:
        return a
    sum = a ^ b
    carry = (a & b) << 1
    return add(sum, carry)

19.找到丢失的数字(一个或多个)

方法:异或 略

20.找到数组[1-n]中重复的一个数,和一个缺失的数

def printTwoElements(arr):
    for i in range(len(arr)):
        if arr[abs(arr[i]) - 1] > 0:
            arr[abs(arr[i]) - 1] = -arr[abs(arr[i]) - 1]
        else:
            print("The repeating element is", abs(arr[i]))
             
    for i in range(len(arr)):
        if arr[i] > 0:
            print("and the missing element is", i + 1)

21.找到下一个最小/最大整数(二进制表示,与原数值有相同多个1) **

def getBit(n, index):
    return ((n & (1<<index))>0)

def setBit(n, index, b):
    if b:
        return n | (1<<index)
    else:
        return n & (~(1<<index))

def getNext(n):
    if n <= 0: 
        return -1

    index = 0
    countOnes = 0

    # Find first one.
    while (not getBit(n, index)):
        index += 1

    # turn on next zero
    while( getBit(n, index) ):
        index += 1
        countOnes += 1
    
    n = setBit(n, index, True)

    # turn off previous one 
    index -= 1
    n = setBit(n, index, False)
    countOnes -= 1

    # set zeros
    i = index - 1
    while (i >= countOnes):
        n = setBit(n, i, False)
        i -= 1

    # set ones
    i = countOnes - 1
    while (i >= 0):
        n = setBit(n, i, True)
        i -= 1

    return n
def getPrevious(n):
    if (n <= 0):
        return -1

    index = 0
    countZeros = 0

    # find first zero
    while( getBit(n, index) ):
        index += 1

    # turn off next 1
    while( not (getBit(n, index)) ):
        index += 1
        countZeros += 1
    
    n = setBit(n, index, False)

    # turn on previous zero
    index -= 1
    n = setBit(n, index, True)
    countZeros -= 1

    # set ones
    i = index - 1
    while (i >= countZeros):
        n = setBit(n, i, True)
        i -= 1

    # set zeros
    i = countZeros - 1
    while (i >= 0):
        n = setBit(n, i, False)
        i -= 1
    
    return n

22.Reservoir Sampling

— 在一个无穷的数据流中,挑选一个概率相等的数字。
import random
def reservoirSampling(items, k):
    sample = items[0:k]

    for i in range(k, len(items)):
        j = random.randrange(1, i + 1)
        if j <= k:
            sample[j - 1] = items[i]

    return sample
23.阶乘结果的尾部0
— 写一个算法,计算n阶乘结果中尾部0的个数
def findTrailingZeros(n):
    count = 0
    i = 5
    while (n / i >= 1):
        count += n//i
        i *= 5
 
    return count

24.最大公约数

def gcd(a, b):
    if b > a:
        return gcd(b, a)

    if a % b == 0:
        return b

    return gcd(b, a % b)  

 

posted @ 2020-05-16 14:11  oldby  阅读(970)  评论(0编辑  收藏  举报