How do I convert a double into a string in C++?
Asked Answered
M

19

206

I need to store a double as a string. I know I can use printf if I wanted to display it, but I just want to store it in a string variable so that I can store it in a map later (as the value, not the key).

Mottle answered 1/12, 2008 at 20:35 Comment(9)
A question to answer your question: why are you storing the double value in a string to store it in a map? Are you going to use the string-ified double as the key? If not, why not leave the double as is?Hasen
Interesting point. Using a double as a map key may fraught with peril, however, as exact comparisons on floating point values always are. Indexing on a string representation avoids the problem.Machiavellian
No, the double is going in as the value in a map<string, string>. I have a bunch of configuration parameters that are of mixed types, and I'm using the map as a convenient place to store them all.Mottle
Why convert it at all? Store it in the map as a double, and avoid the conversion to and from.Faux
I'm storing strings in the map because I have multiple types to validate and store.Mottle
That still sounds like a call for objects. A union would work. Each the object to insert various values into it, and have it self validate.Faux
I only have a bunch of name/value pairs in a file. It doesn't call for objects.Mottle
Using a double as a key, no matter if with or without conversion to string, sounds like a design mistake. A double is fuzzy, but a key needs to be a unique identifier.Charland
@Konstantin I wasn't using a double as a key.Mottle
D
198

The boost (tm) way:

std::string str = boost::lexical_cast<std::string>(dbl);

The Standard C++ way:

std::ostringstream strs;
strs << dbl;
std::string str = strs.str();

Note: Don't forget #include <sstream>

Dibbrun answered 1/12, 2008 at 20:42 Comment(7)
I think boost::lexical_cast pretty much IS the standard C++ way, just nicely packaged for you. BTW, litb, you have a minor typo in there -- "boot:lexical_cast".Machiavellian
boost::lexical_cast is not just a simple wrapper around the stringstream code. Many of the conversion routines are implemented inline. According to the performance measurements on the bottom of this page (boost.org/doc/libs/1_47_0/libs/conversion/lexical_cast.htm), boost::lexical_cast is faster than using stringstreams and, in most cases, faster than scanf/printfLigule
@Ferr who said it was a simple wrapper? And thanks for providing the link, I actually did think it was more or less a simple wrapper :)Dibbrun
don't forget to #include <sstream> for the c++ way :)Boloney
For the sake of documentation, if you don't #include <sstream>, you'll get an error "incomplete type is not allowed."Bossy
Will there be a data loss when using this?Townsend
@jeffrycopps Yes there will in the ostringstream version. If you want to represent the double fully enough to round-trip you need to add something like std::setprecision(std::numeric_limits<double>::max_digits10)Chauchaucer
O
237
// The C way:
char buffer[32];
snprintf(buffer, sizeof(buffer), "%g", myDoubleVar);

// The C++03 way:
std::ostringstream sstream;
sstream << myDoubleVar;
std::string varAsString = sstream.str();

// The C++11 way:
std::string varAsString = std::to_string(myDoubleVar);

// The boost way:
std::string varAsString = boost::lexical_cast<std::string>(myDoubleVar);
Odontoid answered 1/12, 2008 at 20:39 Comment(2)
Upvoted for the C++ 11 way. I am new to C++, and didn't realize that there was a to_string function. I'm using Microsoft Visual C++ 2013.Bossy
Important note: "std::to_string" has a precision of 6 digits. So the resulting string is basically a float and not a double.Gardal
D
198

The boost (tm) way:

std::string str = boost::lexical_cast<std::string>(dbl);

The Standard C++ way:

std::ostringstream strs;
strs << dbl;
std::string str = strs.str();

Note: Don't forget #include <sstream>

Dibbrun answered 1/12, 2008 at 20:42 Comment(7)
I think boost::lexical_cast pretty much IS the standard C++ way, just nicely packaged for you. BTW, litb, you have a minor typo in there -- "boot:lexical_cast".Machiavellian
boost::lexical_cast is not just a simple wrapper around the stringstream code. Many of the conversion routines are implemented inline. According to the performance measurements on the bottom of this page (boost.org/doc/libs/1_47_0/libs/conversion/lexical_cast.htm), boost::lexical_cast is faster than using stringstreams and, in most cases, faster than scanf/printfLigule
@Ferr who said it was a simple wrapper? And thanks for providing the link, I actually did think it was more or less a simple wrapper :)Dibbrun
don't forget to #include <sstream> for the c++ way :)Boloney
For the sake of documentation, if you don't #include <sstream>, you'll get an error "incomplete type is not allowed."Bossy
Will there be a data loss when using this?Townsend
@jeffrycopps Yes there will in the ostringstream version. If you want to represent the double fully enough to round-trip you need to add something like std::setprecision(std::numeric_limits<double>::max_digits10)Chauchaucer
H
148

The Standard C++11 way (if you don't care about the output format):

#include <string>

auto str = std::to_string(42.5); 

to_string is a new library function introduced in N1803 (r0), N1982 (r1) and N2408 (r2) "Simple Numeric Access". There are also the stod function to perform the reverse operation.

If you do want to have a different output format than "%f", use the snprintf or ostringstream methods as illustrated in other answers.

Hydrodynamics answered 4/11, 2011 at 19:9 Comment(5)
oh yeah baby. to_string and stod both work in Visual Studio 11.Venu
Oh dear baby... to_string doesn't appear to work in VisualStudio 2010 ): That, or I don't know what I'm doing (very possible)Dunno
Is there any way to make this function not add more decimals than needed? When I convert the double 8.0 it gives me the string "8.000000", while "8" would be perfectly fine.Sacksen
you could just do something like for(int lsd=str.len(); lsd>0 && str[lsd] == '0'; lsd--); str = str.substr(lsd);Wiggs
This doesn't work for small numbers... eg: 1e-9 produces 0.000000Atlantic
S
32

You can use std::to_string in C++11

double d = 3.0;
std::string str = std::to_string(d);
Sather answered 27/3, 2017 at 12:35 Comment(5)
My numbers were really small, and std::to_string() simply returned 0.000000 and not in the scientific form.Bisectrix
@erfan how to overcome that issue?Choli
@Choli one way would be to use std::stringstream myStringStream and then do myStringStream << myDouble. you can also use std::setprecision(x)Bisectrix
@erfan that is a good one, thanks. Any shorter than that?Choli
how is this answer different from kennytm's?Ommiad
F
24

If you use C++, avoid sprintf. It's un-C++y and has several problems. Stringstreams are the method of choice, preferably encapsulated as in Boost.LexicalCast which can be done quite easily:

template <typename T>
std::string to_string(T const& value) {
    stringstream sstr;
    sstr << value;
    return sstr.str();
}

Usage:

string s = to_string(42.5);
Fenton answered 1/12, 2008 at 20:41 Comment(0)
U
10

sprintf is okay, but in C++, the better, safer, and also slightly slower way of doing the conversion is with stringstream:

#include <sstream>
#include <string>

// In some function:
double d = 453.23;
std::ostringstream os;
os << d;
std::string str = os.str();

You can also use Boost.LexicalCast:

#include <boost/lexical_cast.hpp>
#include <string>

// In some function:
double d = 453.23;
std::string str = boost::lexical_cast<string>(d);

In both instances, str should be "453.23" afterward. LexicalCast has some advantages in that it ensures the transformation is complete. It uses stringstreams internally.

Unavailing answered 1/12, 2008 at 20:41 Comment(0)
R
9

I would look at the C++ String Toolkit Libary. Just posted a similar answer elsewhere. I have found it very fast and reliable.

#include <strtk.hpp>

double pi = M_PI;
std::string pi_as_string  = strtk::type_to_string<double>( pi );
Ray answered 8/6, 2015 at 15:48 Comment(0)
P
5

The problem with lexical_cast is the inability to define precision. Normally if you are converting a double to a string, it is because you want to print it out. If the precision is too much or too little, it would affect your output.

Piece answered 22/9, 2009 at 15:29 Comment(0)
G
5

The easiest way to convert a double into a string is via std::to_string but unfortunately it's pretty broken up to C++23 (e.g. it poorly handles small and large in magnitude numbers due to fixed format) although it may be fixed in C++26.

Until std::to_string is fixed you can use C++20 std::format, e.g.

std::string s = std::format("{}", 0.42); // s == "0.42"

Disclaimer: I'm the author of C++20 std::format.

Genitals answered 14/12, 2023 at 4:53 Comment(0)
L
3

You could also use stringstream.

Liebermann answered 1/12, 2008 at 20:37 Comment(0)
C
3

Heh, I just wrote this (unrelated to this question):

string temp = "";
stringstream outStream;
double ratio = (currentImage->width*1.0f)/currentImage->height;
outStream << " R: " << ratio;
temp = outStream.str();

/* rest of the code */
Cordon answered 1/12, 2008 at 20:41 Comment(0)
D
3

Normaly for this operations you have to use the C default ecvt, fcvt or gcvt Functions:

/* gcvt example */
#include <stdio.h>
#include <stdlib.h>

main ()
{
  char buffer [20];
  gcvt (1365.249,6,buffer);
  puts (buffer);
  gcvt (1365.249,3,buffer);
  puts (buffer);
  return 0;
}

Output:
1365.25
1.37e+003   

As a Function:

void double_to_char(double f,char * buffer){
  gcvt(f,10,buffer);
}
Dogy answered 21/11, 2015 at 14:42 Comment(0)
C
2

Take a look at sprintf() and family.

Churr answered 1/12, 2008 at 20:37 Comment(2)
I mentioned printf because googling turned up a bunch of articles that say to convert from a double to a string you use printf. They make the assumption that the only thing you could be doing is printing, which in my case is false.Mottle
why you vote -1? I think sprintf is good. @BilltheLizard, sprint prints something to a char * not screen. Someone answered c method still got a lot of vote.Flummox
H
2

You may want to read my prior posting on SO. (Macro'ed version with a temporary ostringstream object.)

For the record: In my own code, I favor snprintf(). With a char array on the local stack, it's not that inefficient. (Well, maybe if you exceeded the array size and looped to do it twice...)

(I've also wrapped it via vsnprintf(). But that costs me some type checking. Yelp if you want the code...)

Hesitant answered 2/12, 2008 at 6:48 Comment(0)
N
1

Note that a string is just a representation of the double and converting it back to double may not result in the same value. Also note that the default string conversion may trim the conversion to a certain precision. In the standard C++ way, you can control the precision as follows:

#include <sstream>
#include <math.h>
#include <iostream>
#include <iomanip>

int main()
{
    std::ostringstream sout;
    sout << M_PI << '\n';
    sout << std::setprecision(99) << M_PI << '\n';
    sout << std::setprecision(3) << M_PI << '\n';
    sout << std::fixed; //now the setprecision() value will look at the decimal part only.
    sout << std::setprecision(3) << M_PI << '\n';
    std::cout << sout.str();
}

which will give you the output

3.14159                                                                                                                                                                            
3.141592653589793115997963468544185161590576171875                                                                                                                                 
3.14                                                                                                                                                                               
3.142  
Neocolonialism answered 8/5, 2021 at 15:2 Comment(0)
B
0

You could try a more compact style:

std::string number_in_string;

double number_in_double;

std::ostringstream output;

number_in_string = (dynamic_cast< std::ostringstream*>(&(output << number_in_double <<

std::endl)))->str(); 
Bearskin answered 10/4, 2014 at 23:36 Comment(0)
D
0

Use to_string().
example :

#include <iostream>   
#include <string>  

using namespace std;
int main ()
{
    string pi = "pi is " + to_string(3.1415926);
    cout<< "pi = "<< pi << endl;

  return 0;
}

run it yourself : http://ideone.com/7ejfaU
These are available as well :

string to_string (int val);
string to_string (long val);
string to_string (long long val);
string to_string (unsigned val);
string to_string (unsigned long val);
string to_string (unsigned long long val);
string to_string (float val);
string to_string (double val);
string to_string (long double val);
Dissimulate answered 11/2, 2016 at 16:55 Comment(0)
H
0

You can convert any thing to anything using this function:

template<class T = std::string, class U>
T to(U a) {
    std::stringstream ss;
    T ret;
    ss << a;
    ss >> ret;
    return ret;
};

usage :

std::string str = to(2.5);
double d = to<double>("2.5");
Hightail answered 5/12, 2016 at 6:11 Comment(0)
K
0

C++17 has introduced: std::to_chars, std::to_chars_result - cppreference.com

std::to_chars_result to_chars( char* first, char* last, float       value,
                               std::chars_format fmt, int precision );
std::to_chars_result to_chars( char* first, char* last, double      value,
                               std::chars_format fmt, int precision );
std::to_chars_result to_chars( char* first, char* last, long double value,
                               std::chars_format fmt, int precision );

Which provide fast low level way to convert floating points into string with some level of format control. This should be fast since no allocation is done, only custom implementation for specific scenario should be faster.

C++20 has introduced high level easy to use format string (equivalent of fmt library):

std::format - cppreference.com

std::format

template< class... Args >
std::string format( /*format_string<Args...>*/ fmt, Args&&... args );

template< class... Args >
std::wstring format( /*wformat_string<Args...>*/ fmt, Args&&... args );

template< class... Args >
std::string format( const std::locale& loc,
                    /*format_string<Args...>*/ fmt, Args&&... args );

template< class... Args >
std::wstring format( const std::locale& loc,
                     /*wformat_string<Args...>*/ fmt, Args&&... args );

Which is quite nice and handy. Should be faster then sprintf.

Karlee answered 23/8, 2022 at 11:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.