Talk:cpp/string/basic string/to string
From cppreference.com
[edit] Not round-trip safe.
Please mention that std::to_string is not round-trip-safe for floating point numbers. Please mention "not round-trip-safe" explaining that converting a double to a std::string and then back to a double will not yield the same number in every case.
Please provide an example of how to perform a round-trip-safe conversion, e.g. maybe something similar to this:
Run this code
#include <iostream> #include <cstdio> #include <iomanip> #include <string> #include <limits> #include <sstream> #include <cassert> void print(const char *msg, double numBefore, const std::string &sNum, bool maybeLucky = false) { double numAfter; std::istringstream(sNum) >> numAfter; std::cout << msg << sNum; if (numBefore == numAfter) { std::cout << " \t(round-trip-safe!"; if (maybeLucky) { std::cout << " - lucky here: too simple number"; } std::cout << ')'; } std::cout << '\n'; } void run(const double x) { const auto maxDig10 = std::numeric_limits<decltype(x)>::max_digits10; std::ostringstream oss; oss << std::setprecision(maxDig10) << x; const std::string sNum = oss.str(); oss.str(""); oss.clear(); oss << std::setprecision(maxDig10-1) << std::scientific << x; const std::string sNumFixed = oss.str(); char sNumAlt[1000]; // must be large enough (todo: what is just-just large enough??) std::snprintf(sNumAlt, sizeof(sNumAlt), "%.*g", maxDig10, x); const std::string sNumBad = std::to_string(x); print("ostringstream -> ", x, sNum); print("ostringstream with std::scientific -> ", x, sNumFixed); print("snprintf -> ", x, sNumAlt); print("std::to_string() -> ", x, sNumBad, true); } int main() { for (double x : {3.3333333333333333333, 0.00033333333333333333333333, 1., 1000000000000000000000., std::numeric_limits<double>::lowest()}) { run(x); std::cout << '\n'; } }
(By the way: how could something so ugly (std::to_string not doing the normal good sane thing), get into the standard??)
- The notes allude to this and the example makes it obvious. That said, it is changing behaviour in C++26 to print the same way std::to_chars does (i.e. shortest representation that preserves round trip) --Ybab321 (talk) 11:49, 26 July 2023 (PDT)
- The size of char sNumAlt[X]; "just-just large enough" buffer could be estimated like this:
Run this code
#include <limits> #include <iostream> int main() { using your_numeric_type_t = long double; // or any other of arithmetic types constexpr std::size_t X = std::numeric_limits<your_numeric_type_t>::max_exponent10 + std::numeric_limits<your_numeric_type_t>::max_exponent10 / 3 + 1 // for possible locale dependent thousands separators + 3 // for sign, null-terminator, digital dot + 6 // trailing 6 digits of "fixed" format + 1 // rounding and safety.) ; std::cout << X << '\n'; }
Possible output:
6587