為什麼這篇浮點 數 問題鄉民發文收入到精華區:因為在浮點 數 問題這個討論話題中,有許多相關的文章在討論,這篇最有參考價值!作者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