[英]How to improve Python code for swapping bits of a 32-bit integer
几天前,我遇到了以下编码面试问题(使用Python )。
给定一个 32 位 integer,交换第 1 位和第 2 位、第 3 位和第 4 位,直到第 31 位和第 32 位。
这是一些起始代码和一个示例:
def swap_bits(num):
# Fill this in.
print(f"0b{swap_bits(0b10101010101010101010101010101010):032b}")
# 0b01010101010101010101010101010101
def swap_bits(num):
num_out = 0
for ii in range(16):
num_out += (num & (2**(2*ii))) << 1
num_out += (num & (2**(2*ii+1))) >> 1
return num_out
print(f"0b{swap_bits(0b10101010101010101010101010101010):032b}")
# Output:
# 0b01010101010101010101010101010101
在效率、代码长度、可读性或其他方面,您有什么改进建议吗? 我将非常感谢您的反馈。 谢谢!
你不需要循环(好吧,在编码面试中,你不能为此使用循环),只需要几个二元运算符:
>>> n = 752846942
>>> bin(n)
'0b101100110111111000100001011110'
>>> bin(((n >> 1) & 0x55555555) | ((n & 0x55555555) << 1))
'0b011100111011110100010010101101'
我在最后一个数字前添加了一个 0,以使结果更容易与 n 进行比较。
有什么诀窍?
将您的数字视为位向量。 交换位对相当于将所有偶数位向左移动一个 position,将所有奇数位向右移动一个 position(假设位编号从 0 开始,从右侧的 LSB 开始)。
向左和向右移动只是一个二进制移位: n << 1
和n >> 1
。 但如果我只是做(n << 1) | (n >> 1)
(n << 1) | (n >> 1)
,我将所有位移动,结果将是错误的。 所以,首先 select 你想要哪些位:偶数位是0x55555555 & n
,奇数位是n & 0xaaaaaaaa
。
所以一种可能性是:
((n & 0x55555555) << 1) | ((n & 0xaaaaaaaa) >> 1)
另一种方法是在移位之后但在二进制之前的 select 位或:
((n << 1) & 0xaaaaaaaa) | ((n >> 1) & 0x55555555)
由于移位反转了位奇偶校验,我只需交换常量 0x55555555 和 0xaaaaaaaa。
为了在二进制文件的两侧获得相同的常数,或者,我 select 在一侧移位之前,在另一侧移位之后。
您绝对可以摆脱代价高昂的求幂。 可以进一步压缩它,但只要每个运算符都是二进制的,复杂性就保持不变。
# to keep the code readable
def swapBits(n, p1, p2):
''' Move p1'th to rightmost side '''
bit1 = (n >> p1) & 1
''' Move p2'th to rightmost side '''
bit2 = (n >> p2) & 1
''' XOR the two bits '''
x = (bit1 ^ bit2)
''' Put the xor bit back to their
original positions '''
x = (x << p1) | (x << p2)
''' XOR 'x' with the original number
so that thetwo sets are swapped '''
result = n ^ x
return result
n = 11
print(bin(n))
k = 0
for i in range(32):
n = swapBits(n, k, k+1)
k+= 2
print(n)
print(bin(n))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.