Namespaces
Variants
Actions

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:

#include <iostream>#include <cstdio>#include <iomanip>#include <string>#include <limits>#include <sstream>#include <cassert>   void print(constchar*msg, double numBefore, conststd::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(constdouble x){constauto maxDig10 =std::numeric_limits<decltype(x)>::max_digits10;std::ostringstream oss; oss <<std::setprecision(maxDig10)<< x;conststd::string sNum = oss.str();   oss.str(""); oss.clear(); oss <<std::setprecision(maxDig10-1)<<std::scientific<< x;conststd::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);   conststd::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:
#include <limits>#include <iostream>   int main(){using your_numeric_type_t =longdouble;// or any other of arithmetic types   constexprstd::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
--Space Mission (talk) 15:59, 26 July 2023 (PDT)
close