b97902HW 板


LINE

有一些容易產生誤解的地方來解釋一下 xD ※ 引述《iForests (森林)》之銘言: : ‧浮點數誤差‧ :   用到 double 時是無論如何都得提到浮點數誤差的,不過這裡只打算亂講。簡單來說 : 是這樣,當你放例如 5 在變數裡時,電腦有可能存 4.9999999999999999999999999999。 : 原則上是沒有差別,但有時候會造成影響。使徒三是個好例子,很多人寫一寫可能會發現 : 印出來的東西竟然有 -0.000,其原因正是因為變數值為像 -0.00000000000002147483647 : 這種後面接了一些怪東西的值(只是隨便打的)。因此輸出時認為它不是 0,而是一個很 : 小很小的負數,所以取 3 位小數時印出 -0.000。 這裡可能會誤導人。雖然原因應該是有一個很小的負數, 但是真的有 -0 這個東西。浮點數格式有 -0 和 +0 :) 我剛才發現 Wiki 還有介紹 xD http://en.wikipedia.org/wiki/%E2%88%920_(number) :   解法方法很簡單,我們加一個很小很小又不至於太小的數給它,例如 1e-10。 : -0.00000000000002147483647 : +0.0000000001 : ------------------------------ : 0.00000000009997852516353 :   這樣一來,用 %.3lf 印出時,答案就會是 0.000 了。 這地方有一點小問題,請看下面。 : ‧數學函式‧ (使用前需先 #include <math.h>) : 首先,π = 2.0 * acos(0.0) = 3.1415926535897932384626433832795。 : ↑這是確確實實的 0.0 而不是表情符號 :   sin()、cos() 等等函數傳入的參數必須使用弳度而非角度,轉換方法高中數學課應 : 有提過,總之:弳度 = 角度 * π / 180。 這邊似乎有點太理想了 xDDDD 上面這一行丟到編譯器去執行 得出來的結果應該是 3.141592653589793115997963468544185161590576171875... (double) 而不是 3.1415926535897932384626433832795... (真的圓周率) 對了,也可以直接用 acos (-1) 喔! : 推 LoganChien:#include <float.h> 之後,你可以用 DBL_MAX 代表極大 09/30 22:40 : → LoganChien:的值(double 可以表示的最大值) 09/30 22:40 : 推 LoganChien:檢查二個 double 是否相同,最好用下面的公式,以減少 09/30 22:48 : → LoganChien:意外。﹝誤差造成的﹞ 09/30 22:48 : → LoganChien:fabs(a - b) < DOUBLE_PRECISION_EPSILON 09/30 22:49 : → LoganChien:let DOUBLE_PRECISION_EPSILON = 1e-9. 09/30 22:49 以上是用絕對誤差來實作,通常也都不會有什麼問題, 不過如果更深入了解 double 的格式的話, 就會知道 double 的誤差是相對的而不是絕對的。 意思是說,對於 1000000000 來說 1e-9 的誤差比較容易發生, 但對於 0.000001 來說 1e-9 就比較不容易了。 (可參考 http://en.wikipedia.org/wiki/IEEE_754-2008 或是計概應該會教) 事實上「浮點數」在字面上就講明小數點是「浮動」的 例如,一般我們寫成 5000 和 0.0005 的兩個數, 就實際上在記憶體中浮點數的儲存方法來看, 應該理解成 5 * 10^3 和 5 * 10^-4 比較恰當 所以誤差是相對的而不是絕對的 (附註:電腦裡面用的是二進位,所以更接近 x * 2^y) 那到底要怎麼去處理浮點數的誤差? 這是個很複雜的問題,端看你的目的而定。 以下這篇文章有講如何比較兩個數字是否一樣: http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm 另外我在這邊提供一個思考的觀點, 到底要允許計算中有多大的誤差可以用最後的要求來定, 例如這次的作業可能要求小數點以下三位, 如果你估計最後的答案是 1000 附近(我只是舉例) 那麼你可能就要讓你整個運算的相對誤差控制在 0.0000005 以內 (0.5e-6) 或是絕對誤差控制在 0.0005 以內 (0.5e-3) 這樣子最後印出來時才會和正確(沒有誤差)的答案比較接近。 運算中的誤差傳遞我相信普物應該有教 xDDD 大致上來說,加法比較不會讓誤差擴大太快 lol 該講的講完了,至於要怎麼寫,套一句劉墉的話,「你自己決定吧!」 : → LoganChien:1. 單純的習慣,我也有看過有人用 1e-8, 1e-10 10/01 00:11 : → LoganChien:2. (印象中) C++ 標準規定 double 最低精確度是 1e-9 10/01 00:12 我相信到這邊 1 應該比較清楚了 至於 2 又要花篇幅講了~ 由於大家學的是 C,加上我沒有看過最新 C++0x 的標準 所以在這裡我只講 C99 的狀況 C99 的標準後面的 Annex F 有講說 C 裡面的 float, double, long double 和 IEC 60559:1989 (也就是 ANSI/IEEE 754-1985) 如何對應 簡單來說,要研究 C 的 double 是怎麼運算的,可以查閱上述標準的 倍精浮點數(double-precision floating point number) 先一下歷史和題外話 xD 其實除了 IEEE 754-1985 以外 還有一個 IEEE 854 的標準也在規定浮點數的運算 啊不過最近 IEEE 754-2008 (又稱 IEEE 754r... 名稱超多 - -|||) 把這兩個舊標準都吃掉了 ANSI/IEEE 754-xxxx 和 ISO/IEC 9899:1999 (C99 的標準) 都是要$$$$$的 還好在官網上面可以下載定案前的 "draft" (非正式版,但是跟正式版很接近這樣) 而且也有很多依照這些標準寫的教學網站,好讀好懂又免費! 好,那這些標準到底怎麼規定誤差的呢? 就像之前講的,這些標準有訂出 double 在記憶體上應該怎麼儲存, 格式會接近這樣: (有一些例外的狀況請自己看文章:http://en.wikipedia.org/wiki/IEEE_floating-point_standard S 1.XXXXXXXXX * 2^YYYYYYY 例如 + 1.00010100 * 2^(+001011) 每個亮色的地方都要花記憶體儲存,而 double 短短 64 bits 就由這三部份所瓜分 S 是正負號(一個 bit 就夠了),YYYYY 的長度決定後面的指數部份可以多大多小, 而 XXXXX 的長度決定了精確度,一切的罪孽都是來自 XXXXX 不夠長 -v- double 的 YYYYXXXX 都比 float 的 YYYYXXXX 還多位, 所以不僅可以處理比較大的數字,數字也可以存比較多位(誤差小)。 double 的 XXXX 只有 52 位~ 電腦要把運算結果塞回記憶體中時,很可能就會產生誤差! 預設的誤差處理方法是二進位的「四捨六入五取雙」 大致上是取最接近運算答案的表示方法~ 講到這邊,聰明的大家應該就可以知道, 單純因為 double 儲存格式產生的相對誤差大約是 2^-5X (有些小細節我不想講了 orz) 大約是 10^-15 ~ 10^-16 左右 (也就是十進位下大約有 15 位 xD 大家可以看前面的圓周率大約第幾位開始爆炸) 至於 C++ 我猜應該也是用同樣的標準玩的 有興趣歡迎補充 xDDDD -- 我在 P2 也有版喔 xD 同 ID 喵~ --



※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 140.112.30.39 ※ 編輯: Favonia 來自: 140.112.30.39 (10/02 21:31)
1F:推 godgunman:是大彼得耶!!!! 10/02 21:41
2F:推 godgunman:話說, 今天助教時間有講IEEE-754 10/02 21:47
※ 編輯: Favonia 來自: 140.112.30.39 (10/02 21:52)
3F:推 wolfdigit: 大彼得好威!!! 10/02 21:54
4F:推 ming1053: 大彼得好威!!! 這篇講的好清楚 10/02 22:04
5F:推 ckclark:-0今天忘了講 10/02 22:17
6F:推 iForests:有神快拜!!!!!(拜) 10/02 22:17
7F:推 scan33scan33: 大彼得好威!!!(拜) 10/02 22:46
8F:推 anfranion:傳說中的大彼得(仰望) 10/02 22:53
9F:推 rewqrewwq:感謝學長指教!(拜) 10/02 23:03
10F:推 Bakaking:娘子,快跟牛魔王出來見上帝! 10/02 23:53
11F:→ benck:推一個 字好多喔 要慢慢消化 10/03 00:07
12F:推 sa072686:有神快拜!!!!!(拜) 10/03 00:22
13F:推 LoganChien:拿香跟拜!(拜) 10/03 00:23
14F:→ LoganChien:獲益良多! 10/03 00:25
※ 編輯: Favonia 來自: 140.112.30.39 (10/03 02:07)
15F:推 pigalan: 大彼得好威!!!(拜) 10/03 22:24







like.gif 您可能會有興趣的文章
icon.png[問題/行為] 貓晚上進房間會不會有憋尿問題
icon.pngRe: [閒聊] 選了錯誤的女孩成為魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一張
icon.png[心得] EMS高領長版毛衣.墨小樓MC1002
icon.png[分享] 丹龍隔熱紙GE55+33+22
icon.png[問題] 清洗洗衣機
icon.png[尋物] 窗台下的空間
icon.png[閒聊] 双極の女神1 木魔爵
icon.png[售車] 新竹 1997 march 1297cc 白色 四門
icon.png[討論] 能從照片感受到攝影者心情嗎
icon.png[狂賀] 賀賀賀賀 賀!島村卯月!總選舉NO.1
icon.png[難過] 羨慕白皮膚的女生
icon.png閱讀文章
icon.png[黑特]
icon.png[問題] SBK S1安裝於安全帽位置
icon.png[分享] 舊woo100絕版開箱!!
icon.pngRe: [無言] 關於小包衛生紙
icon.png[開箱] E5-2683V3 RX480Strix 快睿C1 簡單測試
icon.png[心得] 蒼の海賊龍 地獄 執行者16PT
icon.png[售車] 1999年Virage iO 1.8EXi
icon.png[心得] 挑戰33 LV10 獅子座pt solo
icon.png[閒聊] 手把手教你不被桶之新手主購教學
icon.png[分享] Civic Type R 量產版官方照無預警流出
icon.png[售車] Golf 4 2.0 銀色 自排
icon.png[出售] Graco提籃汽座(有底座)2000元誠可議
icon.png[問題] 請問補牙材質掉了還能再補嗎?(台中半年內
icon.png[問題] 44th 單曲 生寫竟然都給重複的啊啊!
icon.png[心得] 華南紅卡/icash 核卡
icon.png[問題] 拔牙矯正這樣正常嗎
icon.png[贈送] 老莫高業 初業 102年版
icon.png[情報] 三大行動支付 本季掀戰火
icon.png[寶寶] 博客來Amos水蠟筆5/1特價五折
icon.pngRe: [心得] 新鮮人一些面試分享
icon.png[心得] 蒼の海賊龍 地獄 麒麟25PT
icon.pngRe: [閒聊] (君の名は。雷慎入) 君名二創漫畫翻譯
icon.pngRe: [閒聊] OGN中場影片:失蹤人口局 (英文字幕)
icon.png[問題] 台灣大哥大4G訊號差
icon.png[出售] [全國]全新千尋侘草LED燈, 水草

請輸入看板名稱,例如:BuyTogether站內搜尋

TOP