algorithm - 交换位算法中的位掩码
问题描述
完全理解一个基本算法有点麻烦,它接受一个数字 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
据我了解,算法的工作原理是
- 检查位置 i 和 j 的位是否不同。如果没有,我们就完成了 bc 交换相同的位与什么都不做是一样的
- 如果它们不同,那么我们通过翻转位来交换它们。我们可以用 XOR 来做到这一点。
我不完全理解的是位掩码的构造是如何工作的。我知道掩码的目标是识别我们想要切换的位子集,但为什么(1 << i) | (x << j)
要这样做呢?我想我看到它一秒钟,然后我失去了它。
编辑:
我想我现在看到了。我们只是创建了两个二进制数,一个在位置上设置了一个位,一个在i
位置上设置了一个位j
。通过对这些进行或运算,我们得到了一个在i
和 j
位置设置位的数字。我们可以将此掩码应用于我们的输入x
,因为x ^ 1
= 0 时x = 1
和 1 时x = 0
交换位。
解决方案
您最初的直觉认为某些东西看起来很可疑是正确的。有一个错字:
> 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。在 C 中:
unsigned swap_bits(unsigned val, int i, int j) {
unsigned b = ((val >> i) ^ (val >> j)) & 1;
return ((b << i) | (b << j)) ^ val;
}
推荐阅读
- asterisk - Asterisk 队列事件
- java - Spring引导控制器映射到反应组件
- c++ - 如何使用 C++ 将测验分数存储在 txt 文件中
- java - 如何在流口水中增加对象字段
- php - PHP方法确定注册的总课程单元是否不超过限制单元
- python - Bin bash:使用给定的 sh 文件参数启动 python 文件
- asp.net - 当前上下文中不存在名称“FormulaIngredents”?
- reactjs - ReactJS 输出控制台日志重复
- visual-studio-code - VSCode Live Share:为两个参与者运行电子应用程序
- sed - 命令错误 - Windows 10 上的 SED (GnuWin)