公式 x & (x - 1) 是如何工作的?
How does the formula x & (x - 1) works?
来自 Hacker's Delight:第 2 版:
这里的公式在这里似乎有点别扭。当x小于1? (如:(如示例中给出)0x0101 1000 - 0x0000 0000 对我来说没有任何意义)前者比第一个和单词也不存储带符号的向量。这是与此处特定的 RISC 相关的东西还是什么?
如本书注释部分所述。粗体字母对应单词的向量,如 x = 00000000。粗体字母不同于浅色面 1。如粗体 1 = 11111111,其中是一个 8 位字。
Edit2: 特别感谢 Paul Hankin 找出这里使用的非常规符号。粗体字表示 32 位大小的字,即 [00000001],浅色 1 表示 C 中的数字 1。
让我们来看看 x-1
做了什么。
假设 x
是一个值 '???? 1000
(?是 0 或 1)
=> x-1 = ???? 0111
=> x & (x-1) = ???? 0000
不管最右边的1放在x
的哪个位置都非常相似。
要求的例子:
x=00001111
=> x-1=00001110
=> x & (x-1) = 00001110
P.s。 x-1 = 00001110 - 00000001 (<=> 00001110 + 11111111)
减 1
由于我们对十进制比对二进制更熟悉,因此有时查看十进制的情况会有所帮助。
十进制减1会怎样?以 1786000 - 1 = 1785999
.
为例
如果用十进制的正数 x
减去 1
:
x
右边的所有零变为9
;
x
最右边的非零数字减1;
- 其他数字不受影响。
现在,在二进制中,它的工作原理完全相同,除了我们只有 0 1
而不是 0 123456789
。
如果用二进制数 x
减去 1
:
x
右边的所有零变为1
;
x
最右边的非零位变为0
;
- 其他位不受影响。
负数呢?令人高兴的是,使用 2 的补码表示负数的行为与正数完全相同。事实上,当查看 x
的位时,您可以从 x
中减去 1
而无需知道 x
是 signed int 还是 unsigned int。
x & (x-1)
让我们从一个例子开始:x = 01011000
。我们可以按照我刚才解释的方式减去 1:
x = 01011000
x-1 = 01010111
现在 bitwise-and 操作的结果是什么 x & (x-1)
?我们取每一列中的两位;如果它们都是 1,我们写 1;如果其中至少有一个是0,我们写0。
x = 01011000
x-1 = 01010111
x&(x-1) = 01010000
发生了什么事?
x
右边的所有零保持为零;
- 由于
x-1
; ,x
最右边的1变为0
- 所有其他位不受影响,因为它们在
x
和 x-1
中相同。
结论:我们已将 x
中最右边的 1 归零,而其他所有位不受影响。
来自 Hacker's Delight:第 2 版:
这里的公式在这里似乎有点别扭。当x小于1? (如:(如示例中给出)0x0101 1000 - 0x0000 0000 对我来说没有任何意义)前者比第一个和单词也不存储带符号的向量。这是与此处特定的 RISC 相关的东西还是什么?
如本书注释部分所述。粗体字母对应单词的向量,如 x = 00000000。粗体字母不同于浅色面 1。如粗体 1 = 11111111,其中是一个 8 位字。
Edit2: 特别感谢 Paul Hankin 找出这里使用的非常规符号。粗体字表示 32 位大小的字,即 [00000001],浅色 1 表示 C 中的数字 1。
让我们来看看 x-1
做了什么。
假设 x
是一个值 '???? 1000
(?是 0 或 1)
=> x-1 = ???? 0111
=> x & (x-1) = ???? 0000
不管最右边的1放在x
的哪个位置都非常相似。
要求的例子:
x=00001111
=> x-1=00001110
=> x & (x-1) = 00001110
P.s。 x-1 = 00001110 - 00000001 (<=> 00001110 + 11111111)
减 1
由于我们对十进制比对二进制更熟悉,因此有时查看十进制的情况会有所帮助。
十进制减1会怎样?以 1786000 - 1 = 1785999
.
如果用十进制的正数 x
减去 1
:
x
右边的所有零变为9
;x
最右边的非零数字减1;- 其他数字不受影响。
现在,在二进制中,它的工作原理完全相同,除了我们只有 0 1
而不是 0 123456789
。
如果用二进制数 x
减去 1
:
x
右边的所有零变为1
;x
最右边的非零位变为0
;- 其他位不受影响。
负数呢?令人高兴的是,使用 2 的补码表示负数的行为与正数完全相同。事实上,当查看 x
的位时,您可以从 x
中减去 1
而无需知道 x
是 signed int 还是 unsigned int。
x & (x-1)
让我们从一个例子开始:x = 01011000
。我们可以按照我刚才解释的方式减去 1:
x = 01011000
x-1 = 01010111
现在 bitwise-and 操作的结果是什么 x & (x-1)
?我们取每一列中的两位;如果它们都是 1,我们写 1;如果其中至少有一个是0,我们写0。
x = 01011000
x-1 = 01010111
x&(x-1) = 01010000
发生了什么事?
x
右边的所有零保持为零;- 由于
x-1
; , - 所有其他位不受影响,因为它们在
x
和x-1
中相同。
x
最右边的1变为0
结论:我们已将 x
中最右边的 1 归零,而其他所有位不受影响。