contributed by < devarajabc >
1-1
__builtin_clz
,使程式不依賴 GNU extension。參考 wikipedia 、quiz3 、浮點數運算和定點數操作
在解釋程式碼之前我們要先思考如何計算
可以分成以下幾個步驟:
假設
而其又可再拆解成:
利用乘法公式可將
為了方便計算,使用
至於要如何得到
接著利用
將遞迴式改寫成:
遞迴的初始條件如下:
若在每次遞迴的過程中都要計算
其中:
為了方便計算,將
將
而
這個時候 有 趣 的 事 情 發生了,當
竟然透過計算
接著就是如何透過程式碼執行以下遞迴式:
初始條件改為:
此時
由於
故
程式運作的流程如下:
x
來儲存並計算 m = 1UL << ((31 - __builtin_clz(x)) & ~1UL)
來記錄 m
b
來計算 int i_sqrt(int x)
{
if (x <= 1) /* Assume x is always positive */
return x;
int z = 0;//c_n
for (int m = 1UL << ((31 - __builtin_clz(x)) & ~1UL); m; m >>= 2) {
int b = z + m;//b = y_m, m = d_m
z >>= 1;
if (x >= b)// x = x_n
x -= b, z += m;
}
return z;
}
sqrt_(26) = 5 // 正確答案應為 5.09901951359.....
測試完之後發現問題很大,在計算非完全平方數的平方根時會出現錯誤答案,
錯誤的原因不難理解,因為在程式的運算過程皆以整數 (int) 形態來儲存變數,為了讓輸出更接近真實答案,我打算使用定點數的技巧來增加精準度。
ffs / fls
取代 __builtin_clz
參考 ffs :
The ffs() function returns the position of the first (least
significant) bit set in the word i. The least significant bit is
position 1 and the most significant position is, for example, 32
or 64.