我认为答案是对第2.9节中getbits示例进行轻微修改的应用。
让我们按以下方式分解它:
Let bitstring x be 1 0 1 1 0 0
Let bitstring y be 1 0 1 1 1 1
positions -------->5 4 3 2 1 0
将p = 4 and n =3
设为参数,我们得到了从x中提取的二进制字符串为0 1 1
。它从第4位开始,到第2位结束,跨越了3个元素。
我们想要做的是用y
的最后三个元素1 1 1
来替换x
中的0 1 1
。
暂时忘记左移/右移,把问题可视化如下:
我们需要从y
的最后三位中提取数字1 1 1
将1 1 1
直接放在x
的位置4 3和2
下面。
用1 1 1
替换0 1 1
,同时保持其余的位不变...
现在让我们更详细地了解一下...
我的第一个语句是:
We need to grab the last three digits from bitstring y which is 1 1 1
从一个二进制字符串中分离出一些特定的比特位,需要首先得到一个全是0的二进制字符串。例如:
0 0 0 0 0 0
。
0具有一种特殊的性质,即对它进行按位'&'运算会产生全0结果,按位'|'运算会还原另一个数值。
但单独使用0在这里没有什么用处...但它告诉我们,如果将y的最后三位与'0'进行按位'|'运算,将得到1 1 1。这里我们不需要关心y中的其他位,因此需要找到一种方法将其它位清零,同时保持最后三位不变。实际上,我们需要的数字是
0 0 0 1 1 1
。
因此,让我们来看一下所需的一系列转换:
Start with -> 0 0 0 0 0 0
apply ~0 -> 1 1 1 1 1 1
lshift by 3 -> 1 1 1 0 0 0
apply ~ -> 0 0 0 1 1 1
& with y -> 0 0 0 1 1 1 & 1 0 1 1 1 1 -> 0 0 0 1 1 1
这样我们就可以将最后三位数字用于设置目的...
我的第二个陈述是:
将 1 1 1 直接放置在位串 x 的位置 4 3 和 2 下方。
在第 2.9 节中的 getbits 示例中可以找到一个提示。我们知道的有关位置 4、3 和 2 的信息可以从值 p = 4 和 n = 3
中得出。其中,p 是位置,n 是比特集的长度。结果发现 p+1-n
给出了比特集相对于右侧比特的偏移量。在这个特定的示例中,p+1-n = 4+1-3 = 2
。
那么...如果我们对字符串 0 0 0 1 1 1
进行左移 2 位,我们得到的就是 0 1 1 1 0 0
。如果你把这个字符串放在 x 下面,你会注意到 1 1 1
与 x 的位置 4 3 和 2
对齐。
我想我终于找到了线索...我最后的陈述是...
在保留其余位不变的情况下,用 1 1 1 替换 0 1 1...
现在让我们回顾一下我们的字符串:
x -> 1 0 1 1 0 0
isolated y -> 0 1 1 1 0 0
对这两个值进行按位或运算可以得到我们在此情况下所需的结果:
1 1 1 1 0 0
但是如果我们有的是1 0 1
而不是1 1 1
,那么这个方法就会失败……所以我们需要更深入挖掘才能找到我们的“银弹”。
让我们再次看一下上面的两个字符串……
x -> bit by bit...1(stays) 0(changes) 1(changes) 1(changes) 0(stays) 0(stays)
理想情况下,我们需要的比特串是1 x x x 0 0
,其中x将被替换为1。
这里有一个直觉的突破,将会对我们有所帮助。
Bitwise complement of isolated y -> 1 0 0 0 1 1
& this with x gives us -> 1 0 0 0 0 0
| this with isolated y -> 1 1 1 1 0 0 (TADA!)
希望这篇长篇文章能帮助人们理性和解决类似的位掩码问题。感谢您的阅读。