位运算是把数字用 二进制 表示之后,对每一位上 0 或者 1 的运算。位运算共有 5 种运算:与、或、异或、左移、右移。
与、或、异或的运算规律:
与 ( & )或 ( | )异或 ( ^ )0 & 0 = 00 | 0 = 00 ^ 0 = 00 & 0 = 01 | 0 = 11 ^ 0 = 10 & 0 = 00 | 1 = 10 ^ 1 = 10 & 0 = 01 | 1 = 11 ^ 1 = 0左移:
左移运算符 m << n 表示把 m 左移 n 位。在左移 n 位的时候,最左边的 n 位将被丢弃,同时在最右边补上 n 个 0 。比如:
00001010 << 2 = 00101000 10001010 << 3 = 01010000Python 代码【结果有点不一样】:
>>> bin(int('0b00001010', 2) << 2).replace('0b', '').zfill(8) '00101000' >>> bin(int('0b10001010', 2) << 3).replace('0b', '').zfill(8) '10001010000' >>> bin(-int('0b00001010', 2) << 2).replace('0b', '').zfill(8) '-0101000'右移:
右移运算符 m >> n 表示把 m 右移 n 位。在右移 n 位的时候,最右边的 n 位将被丢弃。但右移时处理最左边位的情形要复杂一点。如果数字是一个无符号树值,则用 0 填补最左边的 n 位;如果数字是一个有符号数值,则用数字的符号位填补最左边的 n 位。也就是说,如果数字原先是一个正数,则右移之后在最左边补 n 个 0 ;如果数字原先是负数,则右移之后在最左边补 n 个 1 。下面是对两个 8 位有符号数进行右移的例子:
00001010 >> 2 = 00000010 10001010 >> 3 = 11110001Python 代码【结果有点不一样】:
>>> bin(int('0b10001010', 2) >> 2).replace('0b', '').zfill(8) '00100010' >>> bin(int('0b10001010', 2) >> 3).replace('0b', '').zfill(8) '00010001' >>> bin(-int('0b10001010', 2) >> 3).replace('0b', '').zfill(8) '-0010010'问题: 请实现一个函数,输入一个整数,输出该数二进制表示中 1 的个数。例如,把 9 表示成二进制是 1001 ,有 2 位是 1 。因此,如果输入 9 ,该函数输出 2
分析: 如果整数不等于 0 ,那么该整数的二进制表示中至少有 1 位是 1 。
先假设这个数的最右边一位是 1 ,那么该数减去 1 后,最右边一位变成了0,其他位不变;再假设最后一位不是 1 而是 0 ,而最右边的 1 在第 m 位,那么该数减去 1 ,第 m 位变成 0 , m 右边的位变成 1 , m 之前的位不变;上面两种情况总结,一个整数减去 1 ,都是把最右边的 1 变成 0 ,如果它后面还有 0 ,那么 0 变成 1 。那么我们把一个整数减去 1 ,与该整数做位运算,相当于把最右边的 1 变成了 0 ,比如 1100 与 1011 做位与运算,得到 1000 。那么一个整数中有多少个 1 就可以做多少次这样的运算。
# -*- coding: utf-8 -*- """ Created on 20-7-1 @author: eln @requirements: PyCharm 2017.2; Python 3.5.5 |Anaconda 5.1.0 (64-bit) @decription: 二进制中 1 的个数 """ def hamming_weigth(n: int) -> int: """ 一个数 n 和 它-1 做与运算,就相当于干掉了最右边的 1 . """ bits = 0 while n: bits += 1 n = (n-1) & n return bits if __name__ == '__main__': print(hamming_weigth(11)) # 3 print(all(bin(n).count('1') == hamming_weigth(n) for n in range(30))) # True执行结果:
/home/eln/anaconda3/envs/eln35/bin/python3.5 /home/eln/PycharmProjects/SphinxDoc/_test/test_bin.py 00010001 00 0000 00 ['00', '00'] 00 即 0 & 0 = 0 01 0001 01 ['00', '01'] 00 即 0 & 1 = 0 02 0010 02 ['00', '10'] 00 即 0 & 2 = 0 03 0011 03 ['00', '11'] 00 即 0 & 3 = 0 04 0100 04 ['01', '00'] 00 即 1 & 0 = 0 05 0101 05 ['01', '01'] 01 即 1 & 1 = 1 06 0110 06 ['01', '10'] 00 即 1 & 2 = 0 07 0111 07 ['01', '11'] 01 即 1 & 3 = 1 08 1000 08 ['10', '00'] 00 即 2 & 0 = 0 09 1001 09 ['10', '01'] 00 即 2 & 1 = 0 10 1010 10 ['10', '10'] 10 即 2 & 2 = 2 11 1011 11 ['10', '11'] 10 即 2 & 3 = 2 12 1100 12 ['11', '00'] 00 即 3 & 0 = 0 13 1101 13 ['11', '01'] 01 即 3 & 1 = 1 14 1110 14 ['11', '10'] 10 即 3 & 2 = 2 15 1111 15 ['11', '11'] 11 即 3 & 3 = 3 Process finished with exit code 0