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
?
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.