[其他] 電腦浮點數實作兩函數問題

看板Math作者 (QQ)時間9月前 (2023/07/19 00:29), 9月前編輯推噓20(20087)
留言107則, 7人參與, 9月前最新討論串1/1
想請問一下如圖這兩個函數f跟g如何化簡讓電腦的誤差最小 https://www.desmos.com/calculator/sjxxpwsfwt 其中f(x) = (2^x-(x+1))/(x(x-1)), 0<=x<=1 g(x) = (x^2+1-2^x)/(x(x-1)), 0<=x<=1 可以看到當x越接近0或是1時, f跟g都會遇到0/0的問題, 很吃浮點數的精度 但是由數學理論值可以知道這兩邊的極限值都存在 因此感覺可以化簡成一個讓電腦可以不用面臨極端值運算的形式 嘗試過把2^x做泰勒展開, 但是後續無窮項還是面臨項數問題... 再請板友幫忙, 謝謝! -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 59.102.225.191 (臺灣) ※ 文章網址: https://www.ptt.cc/bbs/Math/M.1689697741.A.853.html

07/19 06:02, 9月前 , 1F
在x=0或1, 分子分母取微分?
07/19 06:02, 1F

07/19 07:57, 9月前 , 2F
當遇到分母為 0 或絕對值低於某值,檢查分子是否亦
07/19 07:57, 2F

07/19 07:59, 9月前 , 3F
接近 0, 如是,則 x 代以另一近似值計算之;否則ERR
07/19 07:59, 3F

07/19 08:14, 9月前 , 4F
分子分母微分法的好處是此例只要 x 靠近 0 或 1 都
07/19 08:14, 4F

07/19 08:15, 9月前 , 5F
能得到正確結果。而上面我提出的方法好處是適用一般
07/19 08:15, 5F

07/19 08:17, 9月前 , 6F
0/0 不定式,而不需改函數式,缺點一當然在此例就是
07/19 08:17, 6F

07/19 08:18, 9月前 , 7F
x 靠近 0 或 1 會遇到除以 0 或溢值問題,另外就是
07/19 08:18, 7F

07/19 08:21, 9月前 , 8F
結果也許不精確,例如第一個函數在 x<=0.1e9 時開始
07/19 08:21, 8F

07/19 08:21, 9月前 , 9F
不正確。
07/19 08:21, 9F
謝謝j大跟y大的idea, 感覺不管微分還是近似值計算, 都還是要決定一個threshold? 即大於某個threshold採取原式, 小於某個threshold採取近似式? 原本是不想要有這個"tunable parameter", 但是目前看起來只能這樣了QQ 好像跟偽逆矩陣一樣, 多小的eigenvalue視作0, 否則視作倒數

07/19 13:41, 9月前 , 10F
試試 bug number algo.
07/19 13:41, 10F

07/19 13:41, 9月前 , 11F
bug-->big
07/19 13:41, 11F
謝謝j大關鍵字

07/20 08:45, 9月前 , 12F
你可以自己寫一個運算用字串去存
07/20 08:45, 12F

07/21 17:11, 9月前 , 13F
樓上那就是上面提的 big number (大數) 演算法
07/21 17:11, 13F
我查big number algorithm沒看到特指哪一種算法, 以及s大說的"用字串去存"指的是什麼 有Reference可以提供嗎? 謝謝!

07/21 22:17, 9月前 , 14F
我估狗搜尋一下,看起來是指用其他方法如字串,陣列來
07/21 22:17, 14F

07/21 22:19, 9月前 , 15F
存例如100位有效數字的數
07/21 22:19, 15F

07/22 17:30, 9月前 , 16F
大數的基本概念就是這樣沒錯, 用大陣列去模擬小學時
07/22 17:30, 16F

07/22 17:30, 9月前 , 17F
做基本加減乘除的演算法
07/22 17:30, 17F

07/22 17:32, 9月前 , 18F
例如 GMP (GNU 多重精度運算庫) 就是一個用 C 語言
07/22 17:32, 18F

07/22 17:32, 9月前 , 19F
寫的這類型函式庫
07/22 17:32, 19F
喔喔 意思就是多開buffer去存更多資料就是了?

07/22 20:01, 9月前 , 20F
不一定要字串,你也可以開個 int64_t 再注意進位
07/22 20:01, 20F

07/22 22:13, 9月前 , 21F
f(x)在 x = 0 附近改寫一下
07/22 22:13, 21F

07/22 22:16, 9月前 , 22F
f(x) = -1/(x-1) + (exp(x ln 2) -1)/x * 1/(x-1)
07/22 22:16, 22F

07/22 22:17, 9月前 , 23F
主要問題是 (exp(x ln 2) -1)/x 這項
07/22 22:17, 23F

07/22 22:18, 9月前 , 24F
我不知道你用什麼,但是大部分函式庫應該都有expm1
07/22 22:18, 24F

07/22 22:20, 9月前 , 25F
改用這個就不會有誤差問題
07/22 22:20, 25F
嗨w大, 第一次看到expm1, 然後查一下還有logp1來增加精度的case, 我再參考, 謝謝!

07/22 22:22, 9月前 , 26F
f(x)拆成兩截,x<0.5的時候用這個,另一頭改用y = 1
07/22 22:22, 26F

07/22 22:22, 9月前 , 27F
-x 當變數,然後expm1比照辦理
07/22 22:22, 27F
了解~

07/22 22:26, 9月前 , 28F
傷浮點精度的是大數相減剩小數,不是0/0
07/22 22:26, 28F
f(x)/g(x)時, 假設數學上是lim_{x→0}f(x) = lim_{x→0}g(x) = 0 且lim_{x→0} f(x)/g(x) = 1 我就是怕x→0時, f跟g這兩個函數在library上的精度不同, 或是函數本身遞增速率不同 導致某個很小的x代入g(x)時, 如果電腦已經因為精度問題return true 0 但是f(x)還沒, 那f(x)/g(x)就是+inf 反之如果是f(x)先return true 0, 那f(x)/g(x)就是+0 我就是怕以上這種情況才會問這篇, 還是說這個並不會發生?

07/22 22:36, 9月前 , 29F
原來有expm1(筆記)
07/22 22:36, 29F

07/22 22:37, 9月前 , 30F
想請問一下,若想知道實際誤差的狀況,準確的計算值要
07/22 22:37, 30F

07/22 22:37, 9月前 , 31F
如何得到?
07/22 22:37, 31F

07/22 22:45, 9月前 , 32F
這個問題不就是「怎麼讓數值運算更精確」
07/22 22:45, 32F
還有 43 則推文
還有 7 段內文
07/23 18:09, 9月前 , 76F
這個"其他方式"就是運用數學關係嘗試找出沒有這種減
07/23 18:09, 76F

07/23 18:09, 9月前 , 77F
的式子 (以 2^x-1 來說可能是泰勒展開後消掉 1)
07/23 18:09, 77F

07/23 18:21, 9月前 , 78F
上面這個例子你就算中間用了三十位有效
07/23 18:21, 78F

07/23 18:21, 9月前 , 79F
減 1 對消後的有效位數就是不足三十位
07/23 18:21, 79F

07/23 18:22, 9月前 , 80F
這就是它被叫做 catastrophic (災難性) 對消的原因
07/23 18:22, 80F
L大這個舉例我了解了, 我如此解釋: (1) 2^(1e-10)=1.00000000006931, 這並不是精度不足 這個值就是在固定精度(假設系統是十五位十進位的系統)下所求出來的最準確值了 理論值就是1.00000000006931abcdefg... 這也是為什麼w大說不是library 2^x的精度問題 (2) 2^(1e-10) - 1的理論值是0.00000000006931abcdefg 而這個理論值在系統是十五位十進位是會寫成6.931abcdefg...*10^(-11) 也就是說, 這個6.931abcdefg...*10^(-11)這個值才是2^(1e-10) - 1 在這個系統的最準確值 但是今天如果照(1)的算法, 我們卻得出6.931*10^(-11)這個不準確的值 這樣理解應該是正確的吧? --------------------------------------- 另外請問各位一個實作問題, 我一直以來都在嵌入式系統寫定點(int32)程式碼 最近第一次有浮點可以用的IC, 寫code的速度飆快, 因為之前算出的數學式就直接刻上去 不用像定點還要控制數值範圍卡overflow之類的 結果最近這幾個需要在意精度的浮點公式讓我有種浮點比定點更難計算與控制誤差的感覺 所以想請板上浮點高手給些建議怎樣的浮點coding style能少踩一點坑 比如之前說的少用相近數相減

07/23 22:45, 9月前 , 81F
原po 07/23 09:44 之後紅色那段的例子
07/23 22:45, 81F

07/23 22:47, 9月前 , 82F
基本上都是10進位可以準確換算成2進位的情況
07/23 22:47, 82F

07/23 22:49, 9月前 , 83F
例如0.5, 0.25, 0.125。像0.1用二進位的角度來看,在
07/23 22:49, 83F

07/23 22:49, 9月前 , 84F
浮點數的系統只能用近似值來表達
07/23 22:49, 84F
這個我理解, 所以我09:44那段特地取剛好可以表達的浮點數x,y來減少討論的變因 不過這樣看起來會有catastrophic cancellation就是不會發生在這種剛好可以表達的

07/23 22:53, 9月前 , 85F
很多數用二進位的角度來看,都是無窮小數,然後搭配
07/23 22:53, 85F

07/23 22:54, 9月前 , 86F
原po對L大舉例的理解,應該就沒問題了
07/23 22:54, 86F
了解~

07/23 22:58, 9月前 , 87F
用比double更大的精度, exp(10^-10)-1 大概會看到更
07/23 22:58, 87F

07/23 22:59, 9月前 , 88F
多小數,但大概有一定比例的小數其實是不準的
07/23 22:59, 88F
如果發生這種事可以先歸類在函數實作不精準吼? 前提應該是基於在某個精度系統下, 函數的實作準度是準到尾數的bits數

07/23 23:01, 9月前 , 89F
不過小數準的位數應該會變多
07/23 23:01, 89F

07/23 23:05, 9月前 , 90F
"是不是要先固定某個精度......才能談相減的誤差" Y
07/23 23:05, 90F
了解~

07/23 23:10, 9月前 , 91F
多項式用"nested"的方式求值除了降低計算量,好像也
07/23 23:10, 91F

07/23 23:11, 9月前 , 92F
算是減少誤差
07/23 23:11, 92F

07/23 23:17, 9月前 , 93F
07/23 10:50 那段,原po實際應用的情況大概不用擔心
07/23 23:17, 93F

07/23 23:20, 9月前 , 94F
會發生.s和p在1,2之間,如果不同,再怎麼近大概是
07/23 23:20, 94F

07/23 23:22, 9月前 , 95F
2e-16等級的差距,要超出浮點數可表示的範圍應該不太
07/23 23:22, 95F

07/23 23:22, 9月前 , 96F
可能
07/23 23:22, 96F
謝謝idea, 放心不少~

07/24 11:15, 9月前 , 97F
07/23 22:59"有一定比例的小數...不準" 我用詞不好
07/24 11:15, 97F

07/24 11:16, 9月前 , 98F
單純是相近的數相減造成不精準
07/24 11:16, 98F

07/24 11:19, 9月前 , 99F
如果原本有15位有效數字,相減後剩5位有效,後面10位
07/24 11:19, 99F

07/24 11:20, 9月前 , 100F
不準.用比double更大的精度,計算前例如有30位有效數
07/24 11:20, 100F

07/24 11:21, 9月前 , 101F
字,相減後還剩20位有效,後面10位不準
07/24 11:21, 101F

07/24 11:23, 9月前 , 102F
用expm1,可能輸入是15位有效數字,輸出是14位有效,
07/24 11:23, 102F

07/24 11:24, 9月前 , 103F
1位不準;用比double更大的精度,輸入30位有效數字,
07/24 11:24, 103F

07/24 11:24, 9月前 , 104F
輸出29位有效,1位不準.大概是這種感覺
07/24 11:24, 104F
這個舉例理解~謝謝P大~

07/24 14:33, 9月前 , 105F
初次接觸浮點數運算的話冼鏡光老師這篇可以看看
07/24 14:33, 105F

07/24 14:33, 9月前 , 106F
blog.dcview.com/article.php?a=Az0HYgNrBDU%3D
07/24 14:33, 106F

07/24 14:34, 9月前 , 107F
包含了我們這裡提過的跟一些其他也很重要的運算概念
07/24 14:34, 107F
謝謝L大的reference~ ※ 編輯: znmkhxrw (59.102.225.191 臺灣), 07/25/2023 01:53:08
文章代碼(AID): #1ajhtDXJ (Math)