请帮助您了解以下功能的逻辑:
def bit_rev (x, b): # reverse b lower bits of x
return sum (1<<(b-1-i) for i in range (0, b) if (x>>i) & 1)
答案 0 :(得分:1)
我看了一下代码,似乎并没有考虑到第b位之后的位。因此,我添加了另一个功能。 (除非您只想达到第b位):
def bit_rev (x, b): # reverse b lower bits of x
return (x >> b << b) + sum(1 << (b - 1 - i) for i in range (0, b) if (x >> i) & 1)
现在解释逻辑。
x >> b << b
因此,假设在此示例中,我们使用5(如x
)和2作为b
。
5的二进制表示形式是101
。因此,我们只想切换最后2位。就是01
。但是,在其他代码中,我们正在交换它们,但忽略了b之后的位。因此,我们忽略了第一个1
(从左到右)。
现在进行第一个操作:
x >> b
是5 >> 2
。向右移2的101是1
,因为我们最终砍掉了01
。 100
或4。现在要吃肉了,
sum(1 << (b - 1 - i) for i in range (0, b) if (x >> i) & 1)
在列表理解之外理解它可能会更容易,因此我将其重写为for循环。
summation = 0
for i in range (0, b):
if (x >> i) & 1:
summation += 1 << (b - 1 - i)
基本上,在每次迭代中,我们都会找到反向位,然后将其添加到总数(summation
)中。
由于发生了很多事情,因此这段代码似乎很难理解。
让我们从for循环本身开始。 for i in range (0, b)
对0到b之间的所有值进行迭代。 (或者您要更改的最后一位)。所有反向操作都将在代码的稍后部分进行。
接下来,我们检查要交换的位是否为1
。在二进制中,仅1
的累加值是总数,因此忽略所有0
的逻辑是合理的。在if (x >> i) & 1:
中。我们将x右移i位。因此,101
位向右移一位是10
。现在,通过执行& 1
,检查最后一位是否为1。基本上& 1
在此程序中执行的操作将忽略第一位以外的所有位。
和按位运算符的工作方式如下:
0101
&1100
=0100
并且要求两者都为真。由于1
之后的所有位都为0,因此它实际上忽略了其余部分。
现在,我们从(x >> i) & 1
得到0或1,Python将所有非零整数处理为True,将零处理为False。这将忽略所有为零的位。
接下来,我们使用summation += 1 << (b - 1 - i)
添加求和。通过使用b - 1 - i
,我们可以知道钻头的位置。然后我们将1移到该位置,然后将其添加到总数中。
在添加两个二进制整数时,您可以将数字加1的位置与以10为基数的位置类似。因此,如果我有数字9000,而我想要的百分位数是1,那么我可以做9000 + 100.这类似于我们在这里所做的事情。我们使用<<
运算符而不是10 ^ i将其移至基数2的左侧。因此,我们将新反转的位设置为原始位。