完整程式碼
本來看到一連串的
不知道其用途,舉實際上的例子來搭配,才不會"舉燭"
取 x = 65 (010001)
可以發現一連串的操作就是從 most significant bit 開始逐漸填滿 1 ,而後面的
取 x = 140737488355328(2^47)
經過前面的 7 次 x |= x>>1 會變成
做
變成
得到 16 個 bit 都是 1 以此類推經過
變成
再用
變成
這樣只要最後的 x + 1 就是大於原先 x 的 2 的最小的冪次方,很適合用於來找分配 memory best fit 要多大
clz 就是 count leading zero 的意思,__builtin_clz(8)的返回值就是29,因為8的二進位制表示为0000 0000 0000 0000 0000 0000 0000 1000,其中前導0有2個9。
如果可以算前面有幾個 0 也可以很快地知道, most significant 的 1 在哪邊,可改寫成
運用
編譯,可以看到以下 machine code
可以發現,編譯出來的 machine code 並沒有多做額外的 function call,還可以看到 brsq 這個指令
好奇 ctz 的其他類似指令, ctz , ffs 會給哪些 x86指令呢
ctz
解釋 leet code 1680. Concatenation of Consecutive Binary Numbers
其中
是用來判斷是否為 2 的冪次方的判斷是,舉 16 為例
16 的 2 進位
10000
16 - 1 = 15 的 2 進位
01111
不難發現, 2 的冪次方與其 -1 的值完全沒有重複的 bit ,故其做 and operation 後必等於 0。
而
表示每次要補上新的數字於 ans 後面時, ans 需要向左 shift len 的長度,騰出空間給新的數字
如果一個數字為 2 的冪次方,表示其寫成 2 進位必定為
00…001..00,只有一個1,只是不確定 1 座落在哪個 bit
可以用 clz (count leading zero) 跟 ctz (count trailing zero) ,加起來後的值判斷其是不是等於 bit length - 1, 如果是就代表 1 只有出現一次,為 2 的冪次方。
同理也可以用類似的概念 ffs (find first set) 來找到第一個 set (從右邊 lsb 數)的 1 ,搭配 clz 看兩者加起來是否等於 bit length 也會代表它就是 2 的冪次方