金融、資料庫、報表等領域頻繁需求:將浮點數轉為定點小數字串(如保留 2 位)。C++ 標準庫無直接函數,printf("%.2f") 雖可用但不型別安全、難擴充。本文提供基於 <sstream> 的通用、安全、高效解決方案。
<sstream>:型別安全、支援任意型別、無緩衝區溢位風險ostream::precision() 的誤區precision() 預設值 6 代表總有效位數,非小數位數!
std::ostringstream oss;
oss << 12345.67; // 預設精度 6 → "12345.7" (截斷!)
oss << 1234567.8; // → "1.23457e+06" (科學記號!)
解決:設定最大精度,禁用科學記號:
#include <sstream>
#include <limits>
#include <string>
std::string FormatFraction(long double value, int decPlaces = 2) {
std::ostringstream oss;
oss.precision(std::numeric_limits::digits10); // 18 位
oss << std::fixed << value; // 固定小數點模式,禁用科學記號
std::string str = oss.str();
// ... 後續處理
}
const char DECIMAL_POINT = '.'; // 歐洲地區為 ','
size_t pos = str.find(DECIMAL_POINT);
if (pos != std::string::npos) {
// 需保留的總長度 = 小數點位置 + 1(小數點) + decPlaces
size_t keepLen = pos + 1 + decPlaces;
if (str.size() > keepLen) {
str[keepLen] = '\0'; // 截斷多餘位數
str = std::string(str.c_str()); // 移除內嵌 '\0' 後的殘留字元
}
// 若不足則自動補零(fixed 模式已保證)
}
return str;
std::fixed 確保輸出總是定點格式(如 123.00),無需手動補零。
#include <sstream>
#include <limits>
#include <string>
std::string FormatFraction(long double value, int decPlaces = 2) {
std::ostringstream oss;
oss.precision(std::numeric_limits::digits10);
oss << std::fixed << value;
std::string str = oss.str();
const char DP = '.';
size_t pos = str.find(DP);
if (pos != std::string::npos) {
size_t keep = pos + 1 + decPlaces;
if (str.size() > keep) {
str[keep] = '\0';
str = std::string(str.c_str());
}
}
return str;
}
// 使用範例
std::cout << FormatFraction(123456789.69999001L) << '\t' // "123456789.69"
<< FormatFraction(12.011L) << std::endl; // "12.01"
void FormatFraction(long double value, std::string& out, int decPlaces = 2) {
std::ostringstream oss;
oss.precision(std::numeric_limits::digits10);
oss << std::fixed << value;
out = oss.str();
// ... 同前處理
}
但現代編譯器 NRVO/RVO 優化極佳,返回值通常零開銷,直觀 API 更優先。
sprintf/std::to_string?| 方法 | 缺點 |
|---|---|
sprintf(buf, "%.2f", v) | 緩衝區溢位風險、非型別安全、需手算緩衝區大小 |
std::to_string | 格式固定(6 位小數)、無法自訂精度、C++11 才支援 |
ostringstream | 型別安全、精度完全可控、可擴充區域設定 |
ostringstream + fixed + max_precision → 字串 → 定位小數點 → 截斷std::fixed 關鍵:保證定點輸出,自動補零,避免科學記號numeric_limits::digits10 給出型別最大十進制精度,一勞永逸FormatFraction(value, decPlaces=2) 即得通用、安全、高效工具函數