Re: [問題] float 精準度觀念問題

作者: Feis (永遠睡不著 @@)   2018-09-19 00:13:10
※ 引述《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 (可愛小孩子)   2018-09-19 03:16:00
大推(Y)
作者: chchwy (mat)   2018-09-19 08:03:00
神解答 格子點的解釋很好懂
作者: sarafciel (Cattuz)   2018-09-20 15:14:00
推格子點的解釋
作者: lovejomi (JOMI)   2018-09-25 16:59:00
針對那三個步驟,算的時候沒有受到誤差限制反而是算完之後3. 會因為要mapping to ieee754而產生誤差 這邊覺得很神奇 不知道cpu怎麼運算的

Links booklink

Contact Us: admin [ a t ] ucptt.com