contributed by < hugo0406
>
版本一
版本一透過右移的操作來得到 ,每當右移一個位元,就對 log 加一,直到找到最高位元。然而當 i 的數值越大,迴圈進行的次數也會越多。
版本二
版本二是將版本一進行改善,透過判斷條件一次右移多個位元來減少迴圈次數。
版本三
的值取決於 i 的 msb 的位置 ,舉 i = 79 為例 , i 的 msb 的位置為 6 , 為 6
可以用 GNU extension __builtin_clz
來得到 msb 前有幾個 0,透過 可得到 msb 的位置,也就是 的值。
Other Built-in Functions Provided by GCC 有對 __built-in_clz
進行說明,說明如下
Built-in Function: int __builtin_clz (unsigned int x)
Returns the number of leading 0-bits in x, starting at the most significant bit position. If x is 0, the result is undefined.
若輸入值為 0 則無定義,因此透過 V | 1
能確保值不為零。
Linux 核心原始程式碼
這段程式碼的運作原理類似於測驗三的版本二,透過數值比較來決定要右移多少個位元,得出
,由於函式要求出 ,因此要把結果進行加一再回傳。
注意到 x--
,是為了要特別處理 2 的冪次方,分析如下:
若 x 為 2 的冪次方 ,則
若 x 非 2 的冪次方 ,則
透過 x--
,這樣可以避免若 x 為 2 的冪次方結果不正確會多 1 的情形。
程式碼改進
原程式碼若輸入 0 ,則在 x--
就會發生 underflow ,會導致結果不正確。
作業要求改善使其能處理 x = 0 的狀況,並仍是 branchless ,可以透過三元運算子來達到。