David Dolson
David Dolson

Reputation: 310

C++: what is the optimal way to convert a double to a string?

What is the most optimal way to achieve the same as this?

void foo(double floatValue, char* stringResult)
{
    sprintf(stringResult, "%f", floatValue);
}

Upvotes: 12

Views: 10148

Answers (12)

Porsche9II
Porsche9II

Reputation: 661

In the future, you can use std::to_chars to write code like https://godbolt.org/z/cEO4Sd . Unfortunately, only VS2017 and VS2019 support part of this functionality...

#include <iostream>
#include <charconv>
#include <system_error>
#include <string_view>
#include <array>

int main()
{
    std::array<char, 10> chars;
    auto [parsed, error] = std::to_chars(
        chars.data(), 
        chars.data() + chars.size(), 
        static_cast<double>(12345.234)
    );
    std::cout << std::string_view(chars.data(), parsed - chars.data());
}

For a lengthy discussion on MSVC details, see https://www.reddit.com/r/cpp/comments/a2mpaj/how_to_use_the_newest_c_string_conversion/eazo82q/

Upvotes: 0

alanc10n
alanc10n

Reputation: 5077

http://www.cplusplus.com/reference/iostream/stringstream/

double d=123.456;
stringstream s;
s << d; // insert d into s

Upvotes: 10

Patel
Patel

Reputation: 429

This is very useful thread. I use sprintf_s for it but I started to doubt if it is really faster than other ways. I came across following document on Boost website which shows performance comparison between Printf/scanf, StringStream and Boost.

Double to String is most common conversion we do in our code, so i'll stick with what i've been using. But, using Boost in other scenarios could be your deciding factor.

http://www.boost.org/doc/libs/1_58_0/doc/html/boost_lexical_cast/performance.html

Upvotes: 0

user1115652
user1115652

Reputation:

Herb Sutter has done an extensive study on the alternatives for converting an int to a string, but I would think his arguments hold for a double as well.

He looks at the balances between safety, efficiency, code clarity and usability in templates.

Read it here: http://www.gotw.ca/publications/mill19.htm

Upvotes: 2

OneOfOne
OneOfOne

Reputation: 99334

If you use the Qt4 frame work you could go :

double d = 5.5;
QString num = QString::number(d);

Upvotes: 1

hb2pencil
hb2pencil

Reputation: 892

The best thing to do would be to build a simple templatized function to convert any streamable type into a string. Here's the way I do it:

#include <sstream>
#include <string>

template <typename T>
const std::string to_string(const T& data)
{
   std::ostringstream conv;
   conv << data;
   return conv.str();
}

If you want a const char* representation, simply substitute conv.str().c_str() in the above.

Upvotes: 3

MSN
MSN

Reputation: 54614

_gcvt or _gcvt_s.

Upvotes: 1

pgast
pgast

Reputation: 1687

On dinkumware STL, the stringstream is filled out by the C library snprintf.

Thus using snprintf formatting directly will be comparable with the STL formatting part. But someone once told me that the whole is greater than or equal to the sum of its known parts.

As it will be platform dependent as to whether stringstream will do an allocation (and I am quite sure that DINKUMWARE DOES NOT YET include a small buffer in stringstream for conversions of single items like yours) it is truely doubtful that ANYTHING that requires an allocation (ESPECIALLY if MULTITHREADED) can compete with snprintf.

In fact (formatting+allocation) has a chance of being really terrible as an allocation and a release might well require 2 full read-modify-write cycles in a multithreaded environment unless the allocation implementation has a thread local small heap.

That being said, if I was truely concerned about performance, I would take the advice from some of the other comments above, change the interface to include a size and use snprintf - i.e.

bool 
foo(const double d, char* const p, const size_t n){
     use snprintf......
     determine if it fit, etc etc etc.
}

If you want a std::string you are still better off using the above and instantiating the string from the resultant char* as there will be 2 allocations + 2 releases involved with the std::stringstream, std::string solution.

BTW I cannot tell if the "string" in the question is std::string or just generic ascii chars usage of "string"

Upvotes: 4

greyfade
greyfade

Reputation: 25657

Boost::lexical_cast<>

Upvotes: 4

David
David

Reputation: 2174

I'd probably go with what you suggested in your question, since there's no built-in ftoa() function and sprintf gives you control over the format. A google search for "ftoa asm" yields some possibly useful results, but I'm not sure you want to go that far.

Upvotes: 2

Michael Krelin - hacker
Michael Krelin - hacker

Reputation: 143189

I'd say sprintf is pretty much the optimal way. You may prefer snprintf over it, but it doesn't have much to do with performance.

Upvotes: 2

Tyler McHenry
Tyler McHenry

Reputation: 76710

I'm sure someone will say boost::lexical_cast, so go for that if you're using boost, but it's basically the same as this anyway:

 #include <sstream>
 #include <string>

 std::string doubleToString(double d)
 {
    std::ostringstream ss;
    ss << d;
    return ss.str();
 }

Note that you could easily make this into a template that works on anything that can be stream-inserted (not just doubles).

Upvotes: 23

Related Questions