金融、資料庫、SMS 等領域常需精確控制浮點數小數位顯示。浮點型別無直接格式化支援,本文介紹「先轉字串、再格式化」的標準化流程,並揭露精度陷阱與解決方案。
#include <string>
#include <sstream>
#include <limits>
std::string do_fraction(long double value, int decplaces = 3) {
// decplaces 包含小數點,如要 2 位小數則傳 3
}
stringstream 預設精度 6 位(總有效位數,非小數位),大數會被科學記號或截斷。須設為型別最大精度:
int prec = std::numeric_limits<long double>::digits10; // 通常 18
std::ostringstream out;
out.precision(prec);
out << value;
std::string str = out.str(); // 完整精度字串
const char DECIMAL_POINT = '.'; // 歐洲地區為 ','
size_t pos = str.find(DECIMAL_POINT);
if (pos != std::string::npos) {
// 找到小數點
size_t fracLen = str.length() - pos - 1; // 實際小數位數
if (fracLen > (size_t)decplaces - 1) { // 超過需求位數
str.erase(pos + decplaces); // 直接截斷(或四捨五入)
} else if (fracLen < (size_t)decplaces - 1) {
str.append(decplaces - 1 - fracLen, '0'); // 補零
}
// 若 decplaces==1 (僅整數),可進一步擦除小數點及後綴
}
return str;
std::string do_fraction(long double value, int decplaces = 3) {
if (decplaces < 1) decplaces = 1;
int prec = std::numeric_limits<long double>::digits10;
std::ostringstream out;
out.precision(prec);
out << value;
std::string str = out.str();
const char DP = '.';
size_t pos = str.find(DP);
if (pos == std::string::npos) { // 無小數點(整數或科學記號)
if (decplaces > 1) {
str += DP;
str.append(decplaces - 1, '0');
}
return str;
}
// 四捨五入邏輯
size_t keep = pos + decplaces; // 保留到小數點後 decplaces-1 位
if (keep < str.length()) {
char next = str[keep];
if (next >= '5') { // 進位
// 從右向左處理進位(略,建議用 std::round 配合縮放)
}
}
if (keep < str.length()) str.erase(keep);
else if (keep > str.length()) str.append(keep - str.length(), '0');
return str;
}
#include <iomanip>
#include <format> // C++20
// C++11 iostream
std::string fmt1(long double v, int d) {
std::ostringstream os;
os << std::fixed << std::setprecision(d-1) << v;
return os.str();
}
// C++20 std::format (推薦)
std::string fmt2(long double v, int d) {
return std::format("{:.{}f}", v, d-1);
}
precision(6) 表示總有效位數 6,非小數 6 位。1.23e+06,破壞字串解析,必須 std::fixed 或設高精度。0.1 無法精確表示,格式化前建議四捨五入至目標精度。',',跨平台請明確指定或用 std::locale::classic()。掌握 <sstream> + <limits> 或現代 std::format,即可從容應對各種浮點數格式化需求。