【问题标题】:Bit mask in swapping bits algorithm交换位算法中的位掩码
【发布时间】:2019-07-30 21:47:04
【问题描述】:

很难完全理解一个基本算法,它接受一个数字 x 并交换位置 i 和 j 的位。这个算法是众所周知的

def swap_bits(x, i, j):
    if (x >> i) & 1 != (x >> j) & 1:
        bit_mask = (1 << i) | (1 << j)
        x ^= bit_mask
    return x

据我了解,算法的工作原理是

  1. 检查位置 i 和 j 的位是否不同。如果没有,我们就完成了 bc 交换相同的位就像什么都不做一样
  2. 如果它们不同,则我们通过翻转位来交换它们。我们可以使用 XOR 来做到这一点。

我不完全理解的是位掩码的构造是如何工作的。我知道掩码的目标是识别我们想要切换的位子集,但为什么(1 &lt;&lt; i) | (x &lt;&lt; j) 是这样做的?我想我看到它一秒钟,然后我失去了它。

编辑:

我想我现在看到了。我们只是创建了两个二进制数,一个在i 位置设置了一个位,一个在j 位置设置了一个位。通过 ORing 这些,我们在i j 位置设置了一个数字。我们可以将此掩码应用于我们的输入x,因为x ^ 1 = 0 时x = 1 和1 时x = 0 交换位。

【问题讨论】:

  • 为了更有趣,这可以调整为无分支,通过 m = ((x &gt;&gt; i) ^ (x &gt;&gt; j)) &amp; 1 和 xoring x by (m &lt;&lt; i) | (m &lt;&lt; j)。这是同一件事:如果位不同,则 m = 1 并且两个位都被翻转(交换它们,因为它们不同),如果位没有不同,则 m = 0 并且没有任何反应。

标签: algorithm binary


【解决方案1】:

您最初的直觉认为某事看起来很可疑是正确的。有错别字:

> def swap_bits(x, i, j):
...     if (x >> i) & 1 != (x >> j) & 1:
...         bit_mask = (1 << i) | (x << j)
...         x ^= bit_mask
...     return x
... 
>>> swap_bits(0x55555, 1, 2)
1048579
>>> hex(swap_bits(0x55555, 1, 2))
'0x100003'
>>> 

答案应该是 0x55553。一个更正的版本会有

  bit_mask = (1 << i) | (1 << j)

我同意这种方法要求if-less 实现的其中一个cmets。在 C 中:

unsigned swap_bits(unsigned val, int i, int j) {
  unsigned b = ((val >> i) ^ (val >> j)) & 1;
  return ((b << i) | (b << j)) ^ val;
}

【讨论】:

  • 很好,但这恰好是帖子中的错字。我同样的问题适用于更正后的(1 &lt;&lt; i) | (1 &lt;&lt; j)
猜你喜欢
  • 2010-11-26
  • 2021-10-05
  • 1970-01-01
  • 2018-03-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-24
  • 2011-02-09
相关资源
最近更新 更多