我目前正在学习位操作和按位运算符,并且正在研究一个练习题,在该练习题中,您必须将 int M 的 [i,j] 子部分合并到 [i,j] 处的 N 中。我以线性方式创建了面具,但在谷歌搜索后我发现 ~0 << j | ((1 << i) - 1) 创建我想要的面具。但是,我不确定为什么。如果有人能提供说明,那就太好了,谢谢。
void merge(int N, int M, int i, int j){
int mask = ~0 << j | ((1 << i) - 1);
N = N & mask; // clearing the bits [i,j] in N
mask = ~(mask); // inverting the mask so that we can isolate [i,j] in
//M
M = M & mask; // clearing the bits in M outside of [i,j]
// merging the subsection [i,j] in M into N at [i,j] by using OR
N = N | M;
}
~0
是“所有 1
位”的数字。当你将它向上移动 j
,你使最不显着j
位到 0
:
1111111111111111 == ~0 == ~0 << 0
1111111111111110 == ~0 << 1
1111111111100000 == ~0 << 5
1111111110000000 == ~0 << 7
1 << i
只是 i + 1
第一个最低有效位打开。
0000000000000001 == 1 << 0
0000000000000010 == 1 << 1
0000000000001000 == 1 << 3
0000000001000000 == 1 << 6
当你从中减去 1 时,有一个从左边一直进位,所以你剩下的是 1 位变为 1 之前的所有位(所以你最终得到第一个 i
最低有效位打开)。
0000000000000000 == (1 << 0) - 1
0000000000000001 == (1 << 1) - 1
0000000000000111 == (1 << 3) - 1
0000000000111111 == (1 << 6) - 1
当你或他们结束时,你会在 j
之间找到一个窗口第最低有效位和 i + 1
第 th 个最低有效位打开(包括)。
1111111110000000 == ~0 << 7
0000000000000111 == (1 << 3) - 1
1111111110000111 == ~0 << 7 | ((1 << 3) - 1)
7 3
当你&
具有此掩码的数字,您清除范围内的位 (i, j] (不包括 i
位本身)。
当你~
掩码,你会得到一个新的掩码,它只会给你范围 (i, j) 中的位。
1111111110000111 == ~0 << 7 | ((1 << 3) - 1)
0000000001111000 == ~(~0 << 7 | ((1 << 3) - 1))
也可以用类似 ((1 << j) - 1) & ~((1 << i) - 1)
的东西来构造.