需要帮助来了解Python代码

时间:2018-07-14 02:58:12

标签: python python-2.7 bit

请帮助您了解以下功能的逻辑:

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)

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(从左到右)。

现在进行第一个操作:

    在我们的例子中,
  1. x >> b5 >> 2。向右移2的101是1,因为我们最终砍掉了01
  2. 接下来,我们将其移回去。我们保证(在Python中)从位移返回0,所以我们现在有了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的左侧。因此,我们将新反转的位设置为原始位。