看板 C_and_CPP 關於我們 聯絡資訊
我理解為什麼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 觀念上有些錯誤 請大家修正一下 謝謝 -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 27.247.37.201 ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1537266560.A.860.html ※ 編輯: lovejomi (27.247.37.201), 09/18/2018 18:36:56 ※ 編輯: lovejomi (27.247.37.201), 09/18/2018 18:44:25
Sanvean: 可以說一下你對 ieee754 的了解嗎?因為如果對 ieee75409/18 19:21
Sanvean: 不是很熟的話,那對大多數 float 實作的討論好像會沒完沒09/18 19:24
Sanvean: 了。09/18 19:24
lovejomi: 理解ieee754表示法的含義 但我對 float的+-*\沒有什麼09/18 19:49
lovejomi: 概念09/18 19:49
lovejomi: 實際在作*\法的時候到底怎麼運做的沒有概念09/18 19:50
※ 編輯: lovejomi (110.28.193.230), 09/18/2018 20:14:20 ※ 編輯: lovejomi (110.28.193.230), 09/18/2018 20:59:20 ※ 編輯: lovejomi (110.28.193.230), 09/18/2018 21:02:52
Sanvean: flaot 天生有很多的洞 https://ideone.com/OZAsGe 09/18 21:03
Sanvean: 計算過程有很大的可能不斷累積誤差 09/18 21:06
eye5002003: 如果一個float x非常接近1的話,那麼x-1應該要等於0的 09/18 21:08
eye5002003: 等一下我完全講錯了 09/18 21:19
eye5002003: 我不懂為何會覺得var==1.0很嚴苛,你應該盡量減少誤差 09/18 21:26
eye5002003: 例如避免一個很大的數字跟很小的數字相加,小數字會直 09/18 21:27
eye5002003: 接蒸發,真的很怕誤差就用GMP吧 09/18 21:28
eye5002003: 還有別拿兩個非常接近的數字相減可以避免出現小數字 09/18 21:39
Sanvean: 對一個有值的浮點數而言,其 accuracy 為 exp x epsilon 09/18 22:01
Sanvean: ^ieee754 09/18 22:41