contributed by < yan112388
>
程式碼解釋
計算非負整數 N
的平方根
log2(N)
含式來計算 N
的以 2 為底的對數,並將結果轉換為整數,儲存在 msb
中,藉此得到 N
的最高非零位的位置while
迴圈,將數字 N
右移(相當於將數字除以 2),直到剩下最高的非零位元,得到該位置a = 1 << msb
,這等同於設置 a
為 2 的 msb
次方,此值將作為初始步長result
被初始化為 0,將用來儲存最終的平方根while
迴圈,只要 a
不為 0,迴圈就會繼續。在每次的迭代中:(result + a) * (result + a)
是否小於或等於 N
,相當於檢查 (result + a)
的平方是否小於或等於 N
a
被加到 result
上,因為 (result + a)
仍然是 N
的平方根的下界a
都會被右移一位,相當於將 a
除以 2,藉此將搜尋的步長做調整a
變為 0 時,迴圈結束,此時 result
包含了 N
的平方根的整數部分result
版本三:
以 Digit-by-digit calculation 方式,數學式的原理與細節尚未搞懂,待釐清。
目的:計算 in
除以 10 的商和餘數,並將結果儲存在 div
和 mod
中
程式碼如下:
欲計算 in
除以 10,10 可以表達為 1.25 * 8
,所以我們可以先計算 0.75 * in
,接著除以 8,就可以得到in
除以 10 的近似值
(in | 1)
亦即 in + 1
,作用為將 in
的最低位元設為 1。
(in | 1) = in
(in | 1) = in + 1
可以將此操作看成是一種數值的修正,計算 0.75 * in
時,實際上是在計算 3 * in / 4
。當 in
是奇數時,此算數為精確的。但是當 in
是偶數時,由於我們進行了除法並向下取整數,結果會比實際的 0.75 * in
略小,加 1 可以補償這個誤差。
q = (q >> 8) + x
都相當於將 q
除以 256,256 可以表達為 2 的 8 次方。在此有 4 行,表示將 x 除以 2 的 32 次方。q
右移 3 個位元,即提取 q 的高位元作為商。((q & ~0x7) + (*div << 1))
亦同於 div * 8 + *div * 2
計算以 2 為底的對數
版本二:
使用了二分搜法的想法
i
右移 16 位,代表著將其範圍縮小到原來的 1/65536重複此過程,檢查輸入是否大於等於 256()、16 () 及 。每次檢查成功,就將結果加上相應的值(),並將 i
右移相應的位數。
版本三
__builtin_clz
,其功能為找到 x 最高位數前面有幾個 0 , x 為 0 時,未定義。31 - __builtin_clz(v)
就等於 v 的最高非零位的位置,也就是 floor(log2(v))
。__builtin_clz(0)
是未定義的這種問題,使用了 v | 1
而非 v
。 v | 1
的作用是將 v
的最低位設為 1,確保了進入 __builtin_clz is never的輸入永遠非0。EWMA 數學式展開如下:
avg->internal
val
流程:
val
值乘以 ,作為初始的 EWMA 值 (val << avg->factor)
internal
值乘以 再減去 internal
,得到 ,對應於公式中的val << avg.factor
將新的樣本值 val
左移 avg->factor
位,相當於將其乘以 進行縮放,對應於公式中的 avg->weight
位,相當於除以 Q:為甚麼 會對應於公式中的 ?
欲求 ,將之展開,得到:
程式碼中:
最後,將 除以 :