[爆卦]浮點 數 問題是什麼?優點缺點精華區懶人包

為什麼這篇浮點 數 問題鄉民發文收入到精華區:因為在浮點 數 問題這個討論話題中,有許多相關的文章在討論,這篇最有參考價值!作者Feis (坐吃山空)看板C_and_CPP標題Re: [問題] float 精準度觀念問題時間...

浮點 數 問題 在 雙橡教育 Instagram 的最佳解答

2021-09-16 10:14:13

【新學期新氣象,限動模板寫下你的新目標!】⁣⁣ ⁣⁣ 還記得今年年初的自己嗎?你是不是默默地期許自己能夠在新的一年培養規律作息與讀書習慣,並成功地兼顧課業與社團的平衡?⁣⁣ ⁣⁣ 半年匆匆地過去了,新學期開始步入軌道了,小編想帶著大家一起回顧上學期的目標,並同時為下學期做些簡單的準備,讓大家能夠在接...


※ 引述《lovejomi (JOMI)》之銘言:
: a. stackoverflow的作法錯了?
: b. 為什麼會把差值當成相等?
: c. 到底這個epsilon 最應該用在哪裡呢?
: d. 是不是把almost_equal當成一個正解 才是正確的浮點數比較相等呢?
: 我用以下tool 把 epsilon 看他hex form 反推一下
: 他是2^-23 = 0.00000011920928955078125f乍看之下跟gcc定義一致
: https://www.h-schmidt.net/FloatConverter/IEEE754.html
: 觀念上有些錯誤
: 請大家修正一下
: 謝謝

浮點數雖然可能因為實作不同而有差異性,但扣除一些特殊的值之後

浮點數型別能毫無誤差表示的數值跟整數能表示的數值性質相似

都是落在數線上的離散格子點.


跟整數不同的地方在於,相鄰的整數格子點間的距離是相等的

但是相鄰的浮點數格子點間的距離可能不相等 (與指數的大小和 epsilon 有關: epsilon * base^exp)



整數: | | | | | | | | | |

(相鄰的整數間都是等寬)


浮點數: | | | | | | | | | | | | | | |

(相鄰的浮點數間距離,會隨著浮點數的大小而可能有所不同)


要透過浮點數做運算時大概有三個步驟

1. 將要計算的數字轉換成浮點數可精確表示的格子點 (可能產生誤差)
2. 對這些在格子點上的數字們做運算
3. 將算出來的結果存在浮點數可精確表示的格子點上 (可能產生誤差)


以對 x + y 做計算為例.

因為 x 或 y 可能不是目前所用浮點數實作可以精確表達的數字

(例如 0.1 在常見的浮點數實作上無法準確落在格子點上)


所以首先要將 x 與 y 轉換到各自最近的浮點數格子點上,此時就產生誤差

(例如 0.1 + 0.1 時會先將兩個 0.1 都轉換到最近的浮點數格子點,造成運算完的結果可能不完全等於 0.2)


假設將 x 轉換到 x', y 轉換到 y',則令

x = x' + dx (dx 表示 x 轉換到格子點 x' 產生的誤差)
y = y' + dy (dy 表示 y 轉換到格子點 y' 產生的誤差)


因此當我們運算 x + y 時,實質上是用 x' + y' 去運算

同時運算的結果,也可能不落在格子點上


假設我們將 x' + y' 運算的結果取名為 z,則將 z 轉換到最近的格子點 z' 的話

z = z' + dz (dz 表示 z 轉換到格子點 z' 產生的誤差)


綜合以上所說,

原本我們想要算 x + y ,也就是 (x' + dx) + (y' + dy) = x' + y' + dx + dy (例如 0.1 + 0.1)

最後卻變成是算出 z', 也就是 z - dz = x' + y' - dz (例如 0.1 + 0.1 的結果)


最後原本想算的和與真正算出的結果間的誤差就變成是 |x + y - z'| = |dx + dy + dz|


如果 |dx + dy + dz| == 0 的話,去比較 x + y == z' 通常是沒問題

但是不為 0 的時候,dx + dy + dz 和的大小範圍就會影響我們判斷是否可能相等時的條件範圍

而我們怎麼知道 dx + dy + dz 的大小範圍呢 ?

這和當時 x, y, z 的大小有關


因為誤差大小通常不會大於浮點數格子點間一半的距離

而浮點數格子點間距離會隨指數與 epsilon 不同而不同

epsilon 跟浮點數實作有關,而指數大小則與目前的值大小有關



這邊 epsilon 表示的是 1 跟下一個比 1 大的浮點數格子點的距離

可以想成不考慮 base^exp 的大小的情況下 (exp = 0),兩個浮點數格子點間最近的距離

(當然這裡我們去掉了一些特殊的值,例如 subnormal number, +-0)


但是因為 base^exp 會放大格子間距離,所以格子間距離要多乘上 base^exp 而與 epsilon * base^exp 有關

因此考慮 dx + dy + dz 這誤差可能的範圍時,要考慮 dx, dy, dz 的大小

而 dx, dy, dz 的大小與 x, y, z 當時的值有關 (影響 base^exp 的大小)

此外還要考慮 epsilon 跟允許的誤差計算次數等



當然我知道我這邊舉 0.1 當例子可能不好 (通常是 subnormal number),只是為了方便理解

草草寫寫,有錯誤疏漏也請不吝指教



※ 編輯: Feis (140.122.83.198), 09/19/2018 00:47:44
cutekid: 大推(Y) 09/19 03:16
chchwy: 神解答 格子點的解釋很好懂 09/19 08:03
sarafciel: 推格子點的解釋 09/20 15:14
lovejomi: 針對那三個步驟,算的時候沒有受到誤差限制反而是算完 09/25 16:59
lovejomi: 之後3. 會因為要mapping to ieee754而產生誤差 這邊覺 09/25 16:59
lovejomi: 得很神奇 不知道cpu怎麼運算的 09/25 16:59

你可能也想看看

搜尋相關網站