contributed by < MathewSu-001 >
若要求得平方根 N
,以 2的冪相加的表示式為
根據 測驗一 以及 Digit-by-digit calculation 所提及的定義, 是迄今為止找到的近似平方根,則 即為所求平方根 。
所以我們就是要去計算出所有 的總和,從 開始加到 ,而求得 只要試驗 是否成立
考量到運算成本問題,一種想法是從上一輪的差值 減去 得到 ,
當 時,找到精確的平方根;如果不是,則 給出平方根的合適近似值,其中 是近似誤差。
進一步調整,將 拆成
藉由位元運算從 推出下一輪
所以可以知道當 時,得到值 就是平方根 N 所求。
結合上述方法撰寫演算法來尋求 ,初始化條件
上述程式碼可以得到 x 最近的偶數符合 。
在以上程式碼中,。所以依照上述的演算法,不斷的迴圈直到 的時候,那所求得的 z 即為 。
__builtin_clz
使用 linux 提供的 __fls 來進行修改。因為他回傳的 return 值是找到 x 最高位數,所以引用方法如下:
從版本一開始看起,
可以知道找尋 的做法就是取得最高位元的次方是多少。
所以在版本二中,
首先就是先看 i 的值有沒有超過 (32 位元的一半),假如有的話將 result 加上 16,並且數值右移 16 位,然後再依次砍半到 看數值有無超過,這相當於找 fls。
所以版本三中,
因為 __builtin_clz
的功用就是回傳 v 中從最高有效位開始的前導零位數,且如果 v 為 0,則結果未定義。所以加上 | 1
就是定義如果 v 為零時,回傳 0。
從測驗一中,我學到 fls 的用途就是找到 v 最高位數,與 31 - __builtin_clz(v | 1)
作用相同,因此我有進行嘗試並且證實最後結果相同。
透過Exponentially Weighted Moving Average(EWMA; 指數加權移動平均)的數學定義:
可以知道程式碼的 ewma_add
的計算方式
在變數上,val
為新的一筆資料;avg
中的 internal
為最後取的平均值,對應到公式中的 ; weight
為權重值,對應到公式中的 ;最後 factor
與 的計算有關係,為縮放因子。
當 avg->internal
為零時,
當 avg->internal
不為零時,
這邊需要注意的是, 介在 0 ~ 1 之間,但這邊的 weight
為大於零的 2 的冪,所以在作法上,原本的除法要變成乘法( bitewise operation 做右移),乘法變成除法( bitewise operation 做左移)。
在一開始我先將程式做改寫,想要知道 x--
的用途:
就發現如果做出這樣的改動的話,程式碼功能就會跟測驗三的 ilog2
相同。因此先做 x--
,然後 return 值時再加一的用途,就是利用 ilog2
會以 2 的冪做為一個區段,原本 return 的值為 k ,但改動後會變成 return 的值為 k+1,達到 ceil 效果。
x = 0
的狀況當 x = 0
時,做 x--
會取得 x = 0xFFFFFFFF
,而導致最後回傳的值是不正確的,所以在做法上參考了 vax-r 同學的做法,只有在 x > 0 才進行減法。