lowbit 與 highbit

jxyanglinus發表於2024-10-29

lowbit

lowbit 在競賽中還是很常見的,比如樹狀陣列就必須要用 lowbit

lowbit 的原理是利用原碼, 反碼, 補碼的性質來獲得數字在二進位制下最低位的 \(1\)。理解了原碼,反碼,補碼,就不難理解 lowbit 了。

lowbit 程式碼如下:

inline int lowbit(int x) {  
    return x & -x;  
}

以一個例子來理解上面的程式碼(假設你已經理解了原碼,反碼,補碼):

  • 我們假設 \(n = 8\)\(8\) 的二進位制為 : \(00001000\)
  • \(8\) 取反的二進位制為:\(11110111\)
  • 再對取反 \(8\) 加一(補碼)的二進位制為:\(11111000\)
  • 進行與操作之後:\(00001000\)
    就得到了我們的 \(lowbit(8) = 8\)

highbit

這個相對來說要少見些。

顧名思義,它乾的事與 lowbit 相反,求的是數字在二進位制下最高位的 \(1\)

其原理是將一個數二進位制下最高位的 \(1\) 及其右面的每一位都補充為 \(1\),然後把最高位右面的都減掉,剩下就是最高位的 \(1\)。程式碼如下:

int highbit(int x){  
    x |= x >> 1;  
    x |= x >> 2;  
    x |= x >> 4;  
    x |= x >> 8;  
    x |= x >> 16;  
    return x - (x >> 1);  
}

為什麼這樣寫呢?

我們假設 \(x\) 在二進位制下只有最高位是 \(1\),其餘位都是 \(0\)。透過 highbit 函式的第一行,我們透過右移 \(1\) 位並與原來的 \(x\) 異或,將 \(x\) 最高位往右一位填充為了 \(1\),現在總共有連續的兩個 \(1\)。接著透過第二行,可以繼續向右填充兩位,現在統共有 \(4\)\(1\) 了。接下來的程式碼以此類推,我們就可以把右面全部填充為 \(1\) 了,最後 x - (x >> 1) 就可以得到我們想要的 highbit 了。

上面的函式返回值是 int 型的,如果用別的型別,可以自行調整右移位數。

相關文章