位运算系列

2020-04-17  本文已影响0人  普朗tong

位操作符

& 与运算 两个位都是 1 时,结果才为 1,否则为 0,如

1 0 0 1 1   
1 1 0 0 1
------------------------------
1 0 0 0 1

| 或运算 两个位都是 0 时,结果才为 0,否则为 1,如

1 0 0 1 1  
1 1 0 0 1
------------------------------
1 1 0 1 1

^ 异或运算,两个位相同则为 0,不同则为 1,如(可以理解为不进位的加法操作)

1 0 0 1 1  
1 1 0 0 1
-----------------------------
0 1 0 1 0

~ 取反运算,0 则变为 1,1 则变为 0,如

1 0 0 1 1
-----------------------------
0 1 1 0 0

左移运算>>,向左进行移位操作,高位丢弃,低位补 0,如

int a = 8;
a << 3;  
移位前:0000 0000 0000 0000 0000 0000 0000 1000
移位后:0000 0000 0000 0000 0000 0000 0100 0000

右移运算<<,向右进行移位操作,对无符号数,高位补 0,对于有符号数,高位补符号位,如

unsigned int a = 8;
a >> 3;
移位前:0000 0000 0000 0000 0000 0000 0000 1000
移位后:0000 0000 0000 0000 0000 0000 0000 0001
​
int a = -8;
a >> 3;
移位前:1111 1111 1111 1111 1111 1111 1111 1000
移位前:1111 1111 1111 1111 1111 1111 1111 1111

常见位运算问题

1.位操作实现乘除法

int a = 2;  
a >> 1; ---> 1  
a << 1; ---> 4  

2.位操作交换两数

//普通操作
void swap(int &a, int &b) {
  a = a + b;
  b = a - b;
  a = a - b;
}

//位与操作
void swap(int &a, int &b) {
  a ^= b;
  b ^= a;
  a ^= b;
}

3.位操作判断奇偶数

if(0 == (a & 1)) {
 //偶数
}

4.位操作交换符号

int reversal(int a) {
  return ~a + 1;
}  

整数取反加1,正好变成其对应的负数(补码表示);负数取反加一,则变为其原码,即正数

5.位操作求绝对值

int abs(int a) {
  int i = a >> 31;
  return i == 0 ? a : (~a + 1);
}

位运算实战技巧系列(Golang实现)

1.技巧1

x & (x - 1) 用于消去x最后一位的1
x = 1100
x - 1 = 1011
x & (x - 1) = 1000
func isPowerOfTwo(n int) bool {
        return n > 0 && n&(n-1) == 0
}
func countPrimeSetBits(L int, R int) int {
    primes := []int{2, 3, 5, 7, 11, 13, 17, 19}
    var res int
    for i := L; i <= R; i++ {
        k := i
        count := 0
        for k != 0 {
            k &= k - 1
            count++
        }
        for __, v := range primes {
            if v == count {
                res++
            }
        }
    }
    return res
} 

2.技巧2

a ^ b ^ b = a
a ^ a = 0
a ^ 0 = a
异或运算满足交换律和结合律
func singleNumber(nums []int) int {
    res := 0
    for _, v := range nums {
        res ^= v
    }
    return res
}
//采用HashMap
func singleNumber(nums []int) int {
    m := make(map[int]int)
    for _, v := range nums {
        m[v]++
    }
    for k, v := range m {
        if v == 1 {
            return k
        }
    }
    return 0
}

//采用位运算
func singleNumber(nums []int) int {
    res, count := 0, 0
    for i := 0; i < 64; i++ {
        count = 0
        for j := 0; j < len(nums); j++ {
            count += (nums[j] >> i) & 1
        }
        res |= (count) % 3 << i
    }
    return res
}

//采用位运算
func singleNumber(nums []int) int {
    a,b := 0,0
    for _,v := range nums {
        a = (a^v) & ^b
        b = (b^v) & ^a
    }
    return a
}
func getSum(a int, b int) int {

    if b == 0 {
        return a
    } else {
        sum := a ^ b
        sum += (a & b) << 1
        return sum
    }
}
上一篇下一篇

猜你喜欢

热点阅读