Re: [討論] 請大家聊聊 JavaScript的缺陷

看板Soft_Job作者 (「雄辯是銀,沉默是金」)時間6小時前 (2026/01/15 21:31), 編輯推噓0(000)
留言0則, 0人參與, 最新討論串20/20 (看更多)
對這問題很好奇, 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), 來自: 101.8.139.147 (臺灣) ※ 文章網址: https://www.ptt.cc/bbs/Soft_Job/M.1768483879.A.369.html
文章代碼(AID): #1fQEmdDf (Soft_Job)
討論串 (同標題文章)
文章代碼(AID): #1fQEmdDf (Soft_Job)