我认为标准 C++ 库中没有任何真正好的解决方案。
我使用尝试几种不同格式的技巧,然后选择最短的文本表示并且文本表示在往返时具有完全相同的值。我用来保存在我的文本文件 (XML) 输出中。
这有时意味着选择精确的十六进制浮点表示。 (可能会破坏您的用例。)
这是代码,我添加了一个表格来生成一些示例,如果它们是最短的,则将它们标记为*,如果它们不往返,则使用 警告 标记.
#include <iomanip>
#include <ios>
#include <iostream>
#include <sstream>
using std::cout;
using std::defaultfloat;
using std::fixed;
using std::hexfloat;
using std::istringstream;
using std::left;
using std::scientific;
using std::setw;
using std::string;
using std::stringstream;
enum class cap { title, middle, end };
static void print(const char* text, double num, cap c) {
stringstream ss;
ss << fixed << num;
auto s = ss.str();
double fn = stod(s);
size_t flen = s.length();
string falert = "";
if (fn != num) { falert = "/!\\"; flen += 100; }
ss.str("");
ss.clear();
ss << scientific << num;
s = ss.str();
double sn = stod(s);
size_t slen = s.length();
string salert = "";
if (sn != num) { salert = "/!\\"; slen += 100; }
ss.str("");
ss.clear();
ss << hexfloat << num;
s = ss.str();
double hn = stod(s);
size_t hlen = s.length();
string halert = "";
if (hn != num) { halert = "/!\\"; hlen += 100; }
ss.str("");
ss.clear();
ss << defaultfloat << num;
s = ss.str();
double dn = stod(s);
size_t dlen = s.length();
string dalert = "";
if (dn != num) { dalert = "/!\\"; dlen += 100; }
char gbuf[256];
sprintf(gbuf, "%g", num);
s = gbuf;
double gn = stod(s);
size_t glen = s.length();
string galert = "";
if (gn != num) { galert = "/!\\"; glen += 100; }
if (flen <= slen && flen <= hlen && flen <= dlen) falert += "*";
if (slen <= flen && slen <= hlen && slen <= dlen) salert += "*";
if (hlen <= flen && hlen <= slen && hlen <= dlen) halert += "*";
if (dlen <= flen && dlen <= hlen && dlen <= slen) dalert += "*";
if (glen <= dlen && glen <= flen && glen <= hlen && glen <= slen) galert += "*";
if (c == cap::title) cout <<
"┌──────────┬────────────┬──────────────────────────┐\n"
"│ number │ iomanip │ representation │\n"
"├──────────┼────────────┼──────────────────────────┤\n"
;
cout << left
<< "│ " << setw(8) << text << " │ fixed │ " << setw(24) << fixed << num << " │" << falert << "\n"
<< "│ " << setw(8) << text << " │ scientific │ " << setw(24) << scientific << num << " │" << salert << "\n"
<< "│ " << setw(8) << text << " │ hexfloat │ " << setw(24) << hexfloat << num << " │" << halert << "\n"
<< "│ " << setw(8) << text << " │ default │ " << setw(24) << defaultfloat << num << " │" << dalert << "\n"
<< "│ " << setw(8) << text << " │ %g │ " << setw(24) << gbuf << " │" << galert << "\n"
;
cout << (c != cap::end ?
"├──────────┼────────────┼──────────────────────────┤\n" :
"└──────────┴────────────┴──────────────────────────┘\n" );
}
static void table() {
print("0.0", 0.0, cap::title);
print("0.01", 0.01, cap::middle);
print("0.00001", 0.00001, cap::middle);
print("1e99" , 1.e+99, cap::middle);
print("0.1" , 0.1, cap::middle);
print("0.2" , 0.2, cap::middle);
print("0.3" , 0.3, cap::middle);
print("0.4" , 0.4, cap::middle);
print("0.5" , 0.5, cap::middle);
print("0.6" , 0.6, cap::middle);
print("0.7" , 0.7, cap::middle);
print("0.8" , 0.8, cap::middle);
print("0.9" , 0.9, cap::middle);
print("NTSC" , 30.0/1001.0, cap::middle);
print("1/3" , 1.0/3.0, cap::end);
}
int main() {
table();
}