contributed by < qianzsh >
回顧這堂課程中所學,我發現跟文章中的故事有所相似,都是注重細節以及在解決真實世界發生的問題。目前為止,我讀完 linux 書的第一章,以及完成部份 lab0-c。
為何你宣稱閱讀後,僅列出隻字片語呢?你沒有其他收穫嗎?
程式碼將 的 拆解成多個 的相乘,再乘以一個小於 的數 ,可以寫成:
之後改寫 裡的 ,再利用 特性,寫成:
我們可以透過以上的等式操作得到 取 後的整數部份加上 , 是 取 後的小數部份,這裡可以把 替換成 ,所以 ,若 則可以用上述的方法取得整數與小數部份,否則 ,以此往復循環直到遞迴深度達到停止條件。
不用列出參考題解,專注在程式碼本體和你的認知上。
程式碼先是透過判斷式 num >= base 判斷是否還有整數部份,若判斷為是則結果加一並對 num/base 繼續遞迴計算,累加出整數部分,反之則透過 for 迴圈以及遞迴來取得 log 後的小數部份,而變數 acc 決定遞迴深度。
閱讀「你所不知道的 C 語言:遞迴呼叫篇」後,用 Tail recursion 這一種特殊形式的遞迴對原程式進行改寫,需要注意的是,GCC/Clang 要編譯器開啟最佳化才會做 tail recursion。
注意精準的用語,參見資訊科技詞彙翻譯
用 Q16.16 改寫,在過程中我注意到從浮點數變換到定點數是不能直接做位元位移;
在 C99 規格書 6.5.7 Bitwise shift operators 第 2 節指出
Each of the operands shall have integer type.
限制只有整數型別能進行 bitwise 操作;
為何不能對浮點數進行 bitwise 操作?列出相關 C 語言規格書的描述。
考量 IEEE 754 浮點數的儲存格式包含符號位元、指數與尾數,進行位元操作的方式與整數不同,且 c語言並沒有對浮點數的位元操作進行定義,因此以下實做使用浮點數的乘除法進行運算。
應探討誤差和其修正。
Q16.16 格式,保留 16 位小數部分,單層的精度為 。
程式碼在迭代的過程, weight 不斷除 2 ,最後在 weight = 2^{-16} 之後的運算 weight 都為 0 ,導致 result 沒辦法加到後續的值。
上述程式碼,當 weight = 2^{-16} ,也就是 weight_fixed = 1 時, weight_fixed 再除 2 , weight_scaled = 0 。
而且,後續 weight 的累積也不會超過 Q16.16 的最小刻度, ,所以這裡不考慮用另外的變數紀錄誤差
那目前計算出來的值 與真實的值 相差在 Q16.16 的最小刻度內,所以若要更為精準的表示,要用 Q8.24 等能表示更多小數點後位數的格式