C++ 双精度到标准::具有动态精度的字符串(不带尾随零)

C++ 双精度到标准::具有动态精度的字符串(不带尾随零),c++,string,double,C++,String,Double,我想将double值转换为std::string。目前我正在写作 return std::to_string(double_value); 但这只返回7位数字,因为内部to_string()仅使用std::vsnprintf和%f格式说明符(另请参见) 我现在可以用%.15f作为格式说明符手动调用std::vsnprintf,但这会导致后面的零 我(在我看来非常明显)现在的目标是采用如下方法: string o1 = to_string(3.14) string o2 = to_string(

我想将
double
值转换为
std::string
。目前我正在写作

return std::to_string(double_value);
但这只返回7位数字,因为内部
to_string()
仅使用
std::vsnprintf
%f
格式说明符(另请参见)

我现在可以用
%.15f
作为格式说明符手动调用
std::vsnprintf
,但这会导致后面的零

我(在我看来非常明显)现在的目标是采用如下方法:

string o1 = to_string(3.14)
string o2 = to_string(3.1415926536)
assert(o1 == "3.14")
assert(o2 == "3.1415926536")
template<typename T>
inline std::string tostr(T value) {
    std::ostringstream s;
    s.precision(std::numeric_limits<T>::digits10);
    s << value;
    return s.str();
}
%.20
输出中修剪尾随的零是一个很好的细节,但是这个答案大约有8年历史了

也许事情变了?我能在C++中用“双精度”转换< <代码>双<代码>吗? 解决方案:

根据s的答案,您可以编写如下通用函数:

string o1 = to_string(3.14)
string o2 = to_string(3.1415926536)
assert(o1 == "3.14")
assert(o2 == "3.1415926536")
template<typename T>
inline std::string tostr(T value) {
    std::ostringstream s;
    s.precision(std::numeric_limits<T>::digits10);
    s << value;
    return s.str();
}
模板
内联标准::字符串tostr(T值){
std::ostringstream s;
s、 精度(标准:数值限制:数字10);
s“3.12000000000000001”)

仍然很奇怪:

也许有人能告诉我为什么
std::to_string(double)
是在C++-11硬代码中引入的
vsnprintf(…,“%f”,…)
而不是像
vsnprintf(%.15g”)
这样的东西,它可以在不影响C代码的情况下得到更精确的表示?

您可以使用字符串流(sstring)使用流操纵器,请参见下面的示例:

  std::stringstream ss1;
  std::stringstream ss2;
  ss1.precision(15);    
  ss1 << 3.14;
  std::cout << ss1.str()<<' '<<("3.14" == ss1.str())<<std::endl;
  ss2.precision(15);
  ss2 << 3.1415926536;
  std::cout << ss2.str()<<' '<<("3.1415926536" == ss2.str())<<std::endl;
std::stringstream ss1;
std::stringstream ss2;
ss1.精度(15);
ss1您可以将字符串流(sstring)与流操纵器一起使用,请参见下面的示例:

  std::stringstream ss1;
  std::stringstream ss2;
  ss1.precision(15);    
  ss1 << 3.14;
  std::cout << ss1.str()<<' '<<("3.14" == ss1.str())<<std::endl;
  ss2.precision(15);
  ss2 << 3.1415926536;
  std::cout << ss2.str()<<' '<<("3.1415926536" == ss2.str())<<std::endl;
std::stringstream ss1;
std::stringstream ss2;
ss1.精度(15);

SS1一个很好的东西是C,它是非常向后兼容的。链接答案中的C代码是八岁的,这并不重要,它仍然可以工作,而且没有任何相关的改变与C11标准。它不应该很难翻译成C++。没有这样的东西是不可能的,除非你真的知道。预先有多少个有效数字,不管它是八岁还是八小时都是好的:好的代码是好的代码。(另外,它是C++……它没有太大的变化)。。您打算如何处理浮点舍入?我尝试了一些简单的方法,将字符添加到字符串中,但是
3.14
在存储在内存中时可能不完全是
3.14
。在不限制数字的情况下,当您想要
2.12
时,可以得到
2.12000000005
。C的一个优点是它是极值Y是向后兼容的。链接答案中的C++代码是八岁的,这并不重要,它仍然可以工作,并且没有任何相关的改变与C11标准。它不应该很难翻译成C++。没有这样的东西是不可能的,除非你事先知道有效数字的数目。不管它是八岁还是八小时都是好的代码是好的代码(加上它是C++……它不会有太大的变化)。。您计划如何处理浮点舍入?我尝试了一些简单的操作,将字符添加到字符串中,但是
3.14
在存储到内存中时可能不完全是
3.14
。在不限制数字的情况下,当您想要
2.12
时,可以获得
2.12000000005
。在本例中,您仍然需要手动输入指定精度。如果不向
%f
添加精度,则使用
vsnprintf()
可以正确修剪,但精度限制为7位。可以将精度设置为15。将流强制转换为字符串时,字符串将不包含“0”在结尾处。您是对的-您不能使用由
双精度
(17)表示的最大小数位数。(请参见我的编辑)在本例中,您仍然必须手动指定精度。使用
vsnprintf()
如果不将精度添加到
%f
中,它将被正确地修剪,但它被限制为7位。您可以将精度设置为15。当您将流强制转换为字符串时,字符串末尾将不包含“0”。您是对的,并且您不能使用由
双精度
表示的最大小数位数(即17位)。(见我的编辑)