contributed by < cyrong
>
1
在此程式中使用了 4 個數字作為類似 bitmask 的作用
分別是 0xFFFF
, 0xFF
, 0xF
, 0x3
將他們以 2 進位在 32 位元表示的話
0xFFFF
: 0000 0000 0000 0000 1111 1111 1111 1111
0x00FF
: 0000 0000 0000 0000 0000 0000 1111 1111
0x000F
: 0000 0000 0000 0000 0000 0000 0000 1111
0x0003
: 0000 0000 0000 0000 0000 0000 0000 0011
以這些數字每次將位元數分成兩半,讓變數 r
紀錄 ceil_log2
值中 2 的冪的部份。
而 shift
最終會有兩種結果,分別是 0, 2,是在程式碼第 14 行處決定最後的值, shift
會從 0 開始分別在 x
的值在 2 的偶數次方之後交替,也就是
x
= 2() ~ 4(), shift
= 0
x
= 5() ~ 16(), shift
= 2
x
= 17() ~ 64(), shift
= 0
x
= 65() ~ 256(), shift
= 2
以此類推,shift
用意在於紀錄 r
所紀錄不到的 ceil_log2
中 2 的倍數的部份。
最後是 x
, x
最終會有三種結果,分別是 1, 2, 3,原因是經過程式碼中 7, 9, 12, 15行,若是符合條件 x
將分別被向右移 16, 8, 4, 2位元,因此最終只會存在 x
的前兩位元,又因為 x
> 1,因此只會有 1, 2, 3 三種可能,觀察這三個值
=
=
=
當 x
= 2, 3 時,代表 ceil_log2
的值會比 x
= 1 時多 1 ,因此在回傳時將 x
向右位移以得知 x
是否為 2 或 3 。
而在 return 的最後的地方 +1 其用意在於取 ceiling 的部份,上述程式碼可以計算出的值為 x
中包含的 2 的指數,也就是說取得的是 , 但為了避免 2 的指數()被計算錯誤為 (),因此在程式碼最開始有 x--
第 16 行先將 shift
往右位移 1 位,因此 shift
的值會是 BITS_PER_LONG
>> 1 ,也就是 64 >> 1 = 32 , t
中的值會是前 32 位元為 0 後 32 位元為 1 。
而在後面的 while 迴圈中,每次將 shift
向右位移 1 位、 t
向右位移 shift
位,這樣的操作下會把 t
的位元中 1 的個數每次減半
while 迴圈中對於 x
, o
的操作則是用 t
判斷 x
中值為 1 最低位元位置,
若是 x & t
== 0 代表 x
中值為 1 的最低位元在 t
的位元中的左半邊 0 的區域,這時就將 x
向右位移 shift
位並且將 o
+= shift
,也就是將 x
中在最低位元為 1 右側的 shift
個 0 給消除,並用 o
將消除掉的個數進行紀錄。
最終會紀錄下消除掉的 0 的個數,但因為 ffs
要尋找的是第一個 1 的位置,因此 o
的初始值為 1。