简体   繁体   中英

double to std::string with dynamic precisicion (without trailing zeros)

I want to convert a double value into a std::string . Currently I'm writing

return std::to_string(double_value);

But this only returns 7 digits because internally to_string() just uses std::vsnprintf with a %f format specifier (see also here ).

I could now just call std::vsnprintf manually with %.15f as format specifier but this leads to trailing zeros.

My (in my eyes very obvious) goal now is to have an approach like this:

string o1 = to_string(3.14)
string o2 = to_string(3.1415926536)
assert(o1 == "3.14")
assert(o2 == "3.1415926536")

Here is a nice elaboration on trimming trailing zeros from the %.20 output but this answer is about 8 years old.

Maybe things have changed? Can I convert a double with double precision without trailing zeros in C++ today?

Solution:

Based on 2man s answer you can write a generic function like this:

template<typename T>
inline std::string tostr(T value) {
    std::ostringstream s;
    s.precision(std::numeric_limits<T>::digits10);
    s << value;
    return s.str();
}

which will behaves like desired for numeric types. Note that I took digits10 rather than max_digits10 to favor a nice decimal representation rather than more digits and trailing ..0000001

Also IMHO it's worth to add that [v][s][n]printf() together with the format string "%.15 g " (rather than 'f') will also trim trailing zeros (won't work with more digits because they could not be represented with 64bit which would lead to things like a trailing '1', eg 3.12 -> "3.1200000000000001")

Still strange :

Maybe someone can tell me why std::to_string(double) which was introduced with C++-11 hard-codes to vsnprintf(..., "%f", ...) rather than so something like vsnprintf("%.15g") which would result in a more precise representation without affecting C code?

You can use string stream (sstring) with stream manipulators, see example below:

  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;

Or you can use boost format. Here's a link !

  std::cout<<format("%.2f") % 3.14 <<std::endl;
  std::cout<<format("%.10f") % 3.1415926536 <<std::endl;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM