c++c++20stdformat

How to express std::setprecision in std::format?


I have this function:

template <typename T>
auto float_to_string(const T& f) -> std::string {
 auto oss = std::ostringstream{};
 oss << std::setprecision(std::numeric_limits<T>::max_digits10) << f;
 return oss.str();
}

I would like replace the stream code with std::format, e.g. something like

template <typename T>
auto float_to_string(const T& f) -> std::string {
 return std::format("{:.{}f}", f, std::numeric_limits<T>::max_digits10);
}

Using this test code:

int main(int, char*[]) {
  std::cout << float_to_string(10.0000114f) << '\n'; 
  std::cout << float_to_string(10.0000114) << '\n'; 
  std::cout << float_to_string(10.0000114l) << '\n'; 
  std::cout << float_to_string(10.0000086f) << '\n'; 
  std::cout << float_to_string(10.0000086) << '\n'; 
  std::cout << float_to_string(10.0000086l) << '\n';

}

I receive this for the old code:

10.0000114
10.0000114
10.0000114
10.0000086
10.000008599999999
10.0000086000000000001

And this for the new code:

10.000011444
10.00001139999999999
10.000011399999999999952
10.000008583
10.00000859999999925
10.000008600000000000101

The old style seems to make more sense to me as it determines the number of relevant digits. Is there a way to reproduce the old result with std::format?


Solution

  • This does this trick:

    std::format("{:.{}g}", f, std::numeric_limits<T>::max_digits10);
    

    Note the g instead of the f in the format specification.