位运算符应用举例(一)

1.两个数字交换

  • 不借助临时变量,交换两个变量的值
var a = 10
var b = 8
a = a ^ b
b = a ^ b
a = a ^ b
print(a)
print(b)

打印结果如下:
8
10

2.求无符号整数二进制中1的个数

2.1 给定一个无符号整数变量,求其二进制中表示“1”的个数,要求算法的执行效率尽可能高

  • 思路:看一个8位整数 10 100 001 ,先判断最后一位是否为1,而“与”操作可以达到目的。可以把这个八位的数字与 00000001 进行“与“操作,如果结果为1,则表示当前八位数的最后1位为1,否则为0。怎么判断第二位呢?向右移位,在延续前面的判断即可。
func countOfOnes(num:UInt) -> UInt {
    var count:UInt = 0
    var temp = num
    while temp != 0 {
        count += temp & 1
        temp = temp >> 1
    }
    print(count)
    return count
}
countOfOnes(num: 1)
countOfOnes(num: 3)
countOfOnes(num: 8)

打印结果如下:
1
2
1

2.2 如果整数的二进制中有较多的0,那么我们每次右移一位做判断会很浪费,怎么改进前面的算法呢?又没有办法让算法的复杂度只和1的个数有关?

  • 思路:为了简化这个问题,我们考虑只有高位有1的情况,如:11 000 000,如何跳过前面低位的6个0,而直接判断第七位的1?我们可以设计11 000 000 和10 111 111(也就是11 000 000 - 1)做“与”操作,消去最低位的1。如果得到的结果为0,说明我们已经找到或者消去里面最后一个1.如果不为0,那么说明我们消去了最低位的1,但是二进制中还有其他的1,我们的计数器要加1,然后继续上面的操作。
    计数器 count = 0
    步骤一:整数不为0,说明二进制里肯定有1,count = 1
    11 000 000 & 10 111 111 = 10 000 000 ()消去第七位的1
    步骤二:结果不为0,说明二进制中还有1,count = 2
    10 000 000 & 01 111 111 = 0 (消去第八位的1)
    步骤三:结果为0,终止,返回count = 2
func countOfOnes(num:UInt) -> UInt {
    var count:UInt = 0
    var temp = num
    while temp != 0 {
        count += 1
        temp = temp & (temp - 1)
    }
    print(count)
    return count
}
countOfOnes(num: 1)
countOfOnes(num: 3)
countOfOnes(num: 8)

打印结果如下:
1
2
1

3.引申:如何判断一个整数为2的整数次幂

给定一个无符号整型(UInt)变量,判断是否为2的整数次幂

  • 思路:一个整数如果是2的整数次方,那么它的二进制表示中有且只有一位是1,而其他所有位都是0。
func isPowerOfTwo(num:UInt) -> Bool {
    return (num & (num - 1)) == 0
}
isPowerOfTwo(num: 1)
isPowerOfTwo(num: 3)
isPowerOfTwo(num: 8)

结果如下:
true
false
true

你可能感兴趣的:(位运算符应用举例(一))