[英]K&R C programming language exercise 2-9
我不明白 K&R C 編程語言第 2 章 2.10 中的練習 2-9:
練習 2-9。 在二進制補碼系統中, x &= (x-1) 刪除 x 中最右邊的 1 位。 解釋為什么。 使用此觀察編寫更快版本的 bitcount 。
bitcount 函數是:
/* bitcount: count 1 bits in x */
int bitcount(unsigned x)
{
int b;
for (b = 0; x != 0; x >>= 1)
if (x & 01)
b++;
return b;
}
該函數在檢查它是否為 bit-1 后刪除最右邊的位,然后彈出最后一位。
我不明白為什么x&(x-1)
刪除最右邊的 1 位? 例如,假設 x 是1010
並且 x-1 是二進制的1001
,並且x&(x-1)
將是1011
,所以最右邊的位將在那里並且是1,我錯在哪里?
另外,練習中提到了二進制補碼,和這個問題有關系嗎?
非常感謝!!!
首先,您需要相信 K&R 是正確的。 其次,你可能對這些詞有一些誤解。
讓我再為你澄清一下。 最右邊的 1 位不是最右邊的位,而是最右邊的位,二進制形式為 1。
讓我們任意假設 x 是 xxxxxxx1000(x 可以是 0 或 1)。 然后從右到左,第四位是“最右邊的1位”。 在這個理解的基礎上,讓我們繼續這個問題。
為什么 x &=(x-1) 可以刪除最右邊的 1 位?
在二進制補碼系統中,-1 用全 1 位模式表示。
所以x-1其實就是x+(-1),也就是xxxxxxx1000+11111111111。 棘手的問題來了。
在最右邊的 1 位之前,所有 0 變為 1,最右邊的 1 位變為 0,並且有進位 1 轉到左側。 並且這個 1 將繼續向最左邊前進並導致溢出,同時,所有 'x' 位仍然是 a,因為 'x'+'1'+'1'(carry) 導致一個 'x' 位。
然后 x & (x-1) 將刪除最右邊的 1 位。
希望你現在能明白。
謝謝。
這里有一個簡單的方法來解釋它。 讓我們任意假設數字 Y 是 xxxxxxx1000(x 可以是 0 或 1)。
xxxxxxx1000 - 1 = xxxxxxx0111
xxxxxxx1000 & xxxxxxx0111 = xxxxxxx0000(看,“最右邊的 1”不見了。)
所以在 Y 變為 0 之前Y &= (Y-1) 的重復次數將是Y中 1 的總數。
為什么x & (x-1)
刪除最右邊的順序位? 試試看:
如果最右邊的位是 1,則 x 有 a a...b1
的二進制表示, x-1
是a...b0
所以按位和將給出a...b1
因為and
和和保持公共位不變1 & 0
是0
否則 x 具有 a a...b10...0
的二進制表示; x-1
是a...b01...1
並且出於與上述相同的原因, x & (x-1)
將是a...b00...0
再次清除最右邊的順序位。
因此,不是掃描所有位以找出哪些是 0 哪些是 1,您只需迭代操作x = x & (x-1)
直到 x 為 0:步數將是 1 位的數量。 它比簡單的實現更有效,因為從統計上講,您將使用一半的步驟。
代碼示例:
int bitcount(unsigned int x) {
int nb = 0;
while (x != 0) {
x &= x-1;
nb++
}
return nb;
}
我已經很晚了(≈ 3.5yrs)但是你的例子有錯誤。
x = 1010 = 10
x - 1 = 1001 = 9
1010 & 1001 = 1000
如您所見,它刪除了 10 中最右邊的位。
7 = 111
6 = 110
5 = 101
4 = 100
3 = 011
2 = 010
1 = 001
0 = 000
觀察任何數字中最右邊的 1 的位置,該數字減去 1 的相同位置的位為 0。因此,將 x 與 x-1 進行 AND 運算將重置(即設置為 0)最右邊的位。
7 & 6 = 111 & 110 = 110 = 6
6 & 5 = 110 & 101 = 100 = 4
5 & 4 = 101 & 100 = 100 = 4
4 & 3 = 010 & 011 = 010 = 2
3 & 2 = 011 & 010 = 010 = 2
2 & 1 = 010 & 001 = 000 = 0
1 & 0 = 001 & 000 = 000 = 0
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.