In C++ , there are multiple functions which are useful in formatted I/O. to_string(), std::ostringstream, boost::lexical_cast(c++17) and sprintf functions are in the list. It returns a string representation of value.
This article will discuss different alternatives to convert double datatype in to string and its comparison on each other .
Commonly in C++ code, the library function std::to_string is to convert any numeric data type in to string type. It works on fundamental numeric types and available since C++11 and is very useful in formatted I/O. It was designed to produce the same results that sprintf would.
Example:
Float f = 3.0
std::string str = std::to_string(f)
With floating point types std::to_string may yield unexpected results as the number of significant digits in the returned string can be zero and The return value may differ significantly from what std::cout prints by default fir double values.
Example:
In the below code, we declared 4 variables of double type ranging from a very small to a very large number to see the various kinds of outputs using each function.
for (const double f : {23.43, 1e-9, 1e40 ,1e-40})
std::cout << "std::cout: " << f << '\n'
<< "to_string: " << std::to_string(f) << "\n\n";
Output:
std::cout: 23.43
to_string: 23.430000
std::cout: 1e-09
to_string: 0.000000
std:cout: 1e+40
to_string: 10000000000000000303786028427003666890752.000000
std::cout: 1e-40
to_string: 0.000000
Here, The scale values for double values are different from what was expected by the value provided. std::to_string() prints every digit, and six decimal places. It has a default precision of six digits which cannot be changed.
A double can also be converted into a string in C++ using stringstream in different ways according to our requirements. Output of the similar code using stringstream is as follows:
Ostringstream ss;
for (const double f : {23.43, 1e-9, 1e40 ,1e-40})
std::cout << "std::cout: " << f << '\n'
<< "to_string: " <<ss.str() << "\n\n";
std::cout: 23.43
to string: 23.43
std::cout:: 1e-09
to string: 1e-09
std::cout:1e+40
to string: 1e+40
std::cout: 1e-40
to string: 1e-40
For large numbers, ostringstream automatically converts it to scientific notation. We can customize to get the output as fixed-point notation than scientific notation. It also has a default precision of six digits and can be customized by setting the precision.
Boost.LexicalCast which is defined in the Library “boost/lexical_cast.hpp” also provides a cast operator, boost::lexical_cast, that can also convert numbers from strings to numeric types like int or double and vice versa. boost::lexical_cast is an alternative to functions like std::stoi(), std::stod() , and std::to_string(), which were added to the standard library in C++11. Now let see the Implementation of this function in a program.
for (const double f : {23.43, 1e-9, 1e-40})
std::cout << "std::cout: " << f << '\n'
<< "lexical_cast: " << lexical_cast<std::string>(f) << "\n\n";
std::cout: 23.43
lexical_cast:: 23.43
std::cout: 1e-09
lexical_cast:: 1e-09
std::cout: 1e40
lexical_cast:: 1e40
std::cout: 1e-40
lexical_cast:: 1e-40
As you can see, the boost version uses exponential notation (1e-40) whereas std::to_string prints digit, and six decimal places and ostringstream can have both fixed and scientific notation as well as to handle customized precision values. I would say ,
- Always use std::to_string to convert any single value to std::string, if precison is not an issue.
- In case of double, use std::string. If you need precision, use std::ostringstream.
- Prefer boost::lexical_cast if you have boost in your project