Soft_Job 板


LINE

怎麼會是banker's rounding? 完全是float/double無法精準代表fraction的問題。 https://www.h-schmidt.net/FloatConverter/IEEE754.html https://www.binaryconvert.com/convert_double.html 你可以看到在float,0.005實際上是0.004999999888241291046142578125 但在double, 0.005是0.00500000000000000010408340855861 浮點只能找個最接近0.005,但並不是真正的0.005。 所以rounding會往上或往下,是取決於最接近的浮點是>5或 <5。 你的程式對了,但你的ai怎麼結論怎麼會是banker's rounding? ※ 引述《descent (「雄辯是銀,沉默是金」)》之銘言: : 對這問題很好奇, c++ 也有類似的情形。 : 1 #include <iostream> : 2 #include <string> : 3 #include <cmath> : 4 using namespace std; : 5 : 6 int main(int argc, char *argv[]) : 7 { : 8 std::cout.precision(2); : 9 cout << fixed << 0.005 << endl; : 10 cout << 0.015 << endl; : 11 cout << 0.025 << endl; : 12 cout << 0.035 << endl; : 13 cout << 0.045 << endl; : 14 cout << 0.055 << endl; : 15 cout << 0.065 << endl; : 16 cout << 0.075 << endl; : 17 cout << 0.085 << endl; : 18 cout << 0.095 << endl; : 19 return 0; : 20 } : n.cpp 執行結果 : 0.01 : 0.01 : 0.03 : 0.04 : 0.04 : 0.06 : 0.07 : 0.07 : 0.09 : 0.10 : 藉由 ai, 終於知道是怎麼回事, 當決定要印出小數點 2 位數時候用的演算法是 : 「偶數捨入法」(Banker's Rounding) 這是很多繪圖、統計或會計系統的規則: : 若剛好在 .5 的位置, 則捨入到最接近的「偶數」。 : 0.005 → 靠近 0.00 還是 0.01? 這裡 0 是偶數, 所以會趨向 0.00, 但在電腦裡 : 0.005 是 0.00500000000000000010 所以它判斷靠近 0.01。 : 0.015 → 靠近 0.01 還是 0.02? 這裡 2 是偶數, 本應往 0.02 走, 但在電腦裡 0.015 : 是 0.0149..., 所以它決定留在 0.01。 : 另外也請 ai 給出一個簡易版本的演算法, 實作 Banker's Rounding。 : fn.cpp : 1 #include <iostream> : 2 #include <iomanip> // 必須包含此庫以使用 setprecision : 3 : 4 #include <cmath> : 5 #include <string> : 6 #include <cstdio> : 7 : 8 using namespace std; : 9 : 10 /** : 11 * 模擬 setprecision(2) + fixed 的行為 : 12 * @param value 要輸出的數值 : 13 * @param precision 小數點後位數 : 14 */ : 15 void my_print_fixed(double value, int precision) { : 16 cout << fixed << setprecision(20) << value << endl; : 17 : 18 // 1. 取得放大倍數 (例如 precision 2 則為 100) : 19 long double multiplier = std::pow(10, precision); : 20 : 21 // 2. 模擬底層捨入規則 : 22 // 注意:std::round 在這裡會反映出 0.015 儲存成 0.01499... 的事實 : 23 double rounded_value = std::round(value * multiplier) / multiplier; : 24 : 25 // 3. 格式化輸出字串 : 26 // 我們用 printf 的格式化字串來模擬輸出流的最後一步 : 27 char format[10]; : 28 sprintf(format, "%%.%df", precision); : 29 printf("Input: %.20f | Result: ", value); : 30 printf(format, rounded_value); : 31 printf("\n"); : 32 } : 33 : 34 int main() { : 35 double n1 = 0.005; : 36 double n2 = 0.015; : 37 : 38 std::cout << "--- 模擬底層數值轉換 ---" << std::endl; : 39 : 40 // 看看 0.005 實際上在想什麼 : 41 my_print_fixed(n1, 2); : 42 : 43 // 看看 0.015 實際上在想什麼 : 44 my_print_fixed(n2, 2); : 45 : 46 n2 = 0.025; : 47 my_print_fixed(n2, 2); : 48 n2 = 0.035; : 49 my_print_fixed(n2, 2); : 50 n2 = 0.045; : 51 my_print_fixed(n2, 2); : 52 n2 = 0.055; : 53 my_print_fixed(n2, 2); : 54 n2 = 0.065; : 55 my_print_fixed(n2, 2); : 56 n2 = 0.075; : 57 my_print_fixed(n2, 2); : 58 n2 = 0.085; : 59 my_print_fixed(n2, 2); : 60 n2 = 0.095; : 61 my_print_fixed(n2, 2); : 62 return 0; : 63 } : list 5 fn.cpp 執行結果 : 1 --- 模擬底層數值轉換 --- : 2 0.00500000000000000010 : 3 Input: 0.00500000000000000010 | Result: 0.01 : 4 0.01499999999999999944 : 5 Input: 0.01499999999999999944 | Result: 0.01 : 6 0.02500000000000000139 : 7 Input: 0.02500000000000000139 | Result: 0.03 : 8 0.03500000000000000333 : 9 Input: 0.03500000000000000333 | Result: 0.04 : 10 0.04499999999999999833 : 11 Input: 0.04499999999999999833 | Result: 0.04 : 12 0.05500000000000000028 : 13 Input: 0.05500000000000000028 | Result: 0.06 : 14 0.06500000000000000222 : 15 Input: 0.06500000000000000222 | Result: 0.07 : 16 0.07499999999999999722 : 17 Input: 0.07499999999999999722 | Result: 0.07 : 18 0.08500000000000000611 : 19 Input: 0.08500000000000000611 | Result: 0.09 : 20 0.09500000000000000111 : 21 Input: 0.09500000000000000111 | Result: 0.10 : 另外注意 fn.cpp L19, 需要用 long double, 如果用 double 結果 0.015 印出來會 : 是 0.02, 因為演算法 L23 value * multiplier 0.014999999999999999 X 100 : 變成是 1.50000000000000000000, 而不是 1.4999, : 需要使用精度更高的 long double 才會是 1.4999。 : ※ 引述《accessdenied (存取違規)》之銘言: : : https://i.imgur.com/inyE92c.jpg : : 有誰可以告訴我,JavaScript 的 toFixed()為什麼遇到1,4,7這幾個數字後面的5不會 : : 進位呢? --



※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 58.114.66.74 (臺灣)
※ 文章網址: https://webptt.com/m.aspx?n=bbs/Soft_Job/M.1768571731.A.634.html
1F:推 sceleton: 推! 01/16 23:39
2F:→ wuyiulin: 同意,我剛剛在看他測資跑起來就想說跟 banker's round 01/17 02:48
3F:→ wuyiulin: ing 有啥關係,不就二進位誤差(#。 01/17 02:48
4F:→ jonathan793: 就...有人大學沒認真念 ai隨便唬就信了 01/17 12:12
5F:→ jonathan793: 糗的是還沾沾自喜發文 01/17 12:12
6F:推 descent: 感謝補充 01/17 13:28







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燈, 水草

請輸入看板名稱,例如:Boy-Girl站內搜尋

TOP