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

作者: lovejomi (JOMI)   2018-09-18 18:29:12
我理解為什麼float會有誤差值
但是今天朋友討論一件事情
if (float_var == 1.0f) 這樣寫到底有什麼錯(我認知是 這樣寫 變數的值要完全跟1.0
四個byte的memcmp要一樣)
1. 在誤差範圍內 (https://en.cppreference.com/w/cpp/types/numeric_limits/epsilo
n)
如果是趨近於1的數字 我這樣判斷會失敗 導致邏輯錯誤? 所以因為這樣條件太嚴苛
對於經過運算後的float數值 很可能有一點點誤差產生就不成立了?
2. 如果是要完全的相等 , 我能把一個float 一個byte一個byte判斷是否相等來判斷是不
是等值嗎?
例如
typedef union
{
float value;
unsigned char bytes[4];
} IEEE754;
IEEE754 one;
one.value = 1.0f;
IEEE754 target;
target.value = input;
然後memcmp 兩者的bytes
還是 float 的== 實作上就是byte compare?
3. 浮點數運算出現誤差,可以理解成 當除不盡 或是 除完小數點超過二進位小數 23位
無法表示
就會產生誤差?
4. 因為看不懂std::numeric_limits<T>::epsilon 的那個almost_equal在幹嘛 所以找了
一下
https://stackoverflow.com/a/17341/588477
這篇的方法好像是有道理但是請看以下測試
https://ideone.com/MH6jJW
我看VC直接寫
#define FLT_EPSILON 1.192092896e-07F // smallest such that 1.0+FLT
_EPSILON != 1.0
GCC我用gcc -E -dM 去dump (我不知道為什麼找不到定義???怎麼解釋 https://tinyurl.
com/y8heekq8 )
#define __FLT_EPSILON__ 1.19209289550781250000e-7F
奇怪為什麼會是這樣
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
觀念上有些錯誤
請大家修正一下
謝謝
作者: Sanvean   2018-09-18 19:21:00
可以說一下你對 ieee754 的了解嗎?因為如果對 ieee754不是很熟的話,那對大多數 float 實作的討論好像會沒完沒了。
作者: lovejomi (JOMI)   2018-09-18 19:49:00
理解ieee754表示法的含義 但我對 float的+-*\沒有什麼概念實際在作*\法的時候到底怎麼運做的沒有概念
作者: Sanvean   2018-09-18 21:03:00
flaot 天生有很多的洞 https://ideone.com/OZAsGe計算過程有很大的可能不斷累積誤差
作者: eye5002003 (下一夜)   2018-09-18 21:08:00
如果一個float x非常接近1的話,那麼x-1應該要等於0的等一下我完全講錯了我不懂為何會覺得var==1.0很嚴苛,你應該盡量減少誤差例如避免一個很大的數字跟很小的數字相加,小數字會直接蒸發,真的很怕誤差就用GMP吧還有別拿兩個非常接近的數字相減可以避免出現小數字
作者: Sanvean   2018-09-18 22:01:00
對一個有值的浮點數而言,其 accuracy 為 exp x epsilon^ieee754

Links booklink

Contact Us: admin [ a t ] ucptt.com