contributed by < gnkuan0712
>
實作geomean
,計算幾何平均數,不能用 FPU
首先根據 IEEE 754
單精度浮點數會有 32 bits,其編碼方式為:
8.5 = 2³ + 1/2¹
轉成二進制為 1000.1
調整成 1.0001 x 2³
01111111 (127)
表示指數為0,所以指數為3時應先+3,表示成10000010 (130)
0001
因此放到mantissa裡就是00010000000000000000000
(共23bits)uint32_t a
的三個部分取出方法
接著兩個單精度浮點數相乘a*b
M_a = (1 << 23) | frac_a;
再做相乘除了以上大概念外,還會遇到像是 mantissa 相乘時會有 overflow 和正規化的問題的問題
IEEE‑754 要求 mantissa 必須是 1.xxxx
的形式,也就是在 1.0~2.0 之間。如果乘出來 ≥ 2.0,就要把尾數右移一位,並把 exponent 加 1。
參考你所不知道的 C 語言: 浮點數運算中有提到浮點數的加法,若超過1也是把其中一個 mantissa 往右移,然後 exp 加一。
所以乘法應當也會有兩種情況
乘積大小 | Bit47 | 代表值範圍 | 處理方式 |
---|---|---|---|
≥ 2.0 | 1 | [2.0, 4.0) | P >>= 24; exp++ |
[1.0,2.0) | 0 | [1.0, 2.0) | P >>= 23; |
最後我認為若要擴展到多個浮點數相乘,應該要一邊做正規化,保持 mantissa 在 23 bits,但這樣會一直遇到精準度遺失的問題。
TODO: 如何最大保留精準度
原本上面的作法是無條件捨取,所以誤差會很顯著,接著參考了 CMU: computer system 中 page 30 有提到可以採用 round 的方式,也就是對 mantissa
做四捨五入。
四捨五入的實作用 bitwise 操作可以是 P 加上 P 的一半再往右移 n 個 bits P = (P + (1ULL << (n - 1))) >> n;
在第11周的隨堂測驗有提到「不管大小寫字母比較」的實做,這是我上課就聽的懂的程式碼
實作流程:
心得:
我認為這個寫法真的超酷的,尤其判斷大小寫不管是哪一個都是做一樣的操作(往左移五個bit),不用再做額外不同的操作
我看到了不斷在試錯,然後做實驗,透過數據來調整下一步方向的開發過程。