Convert float to string with precision & number of decimal digits specified?

How do you convert a float to a string in C++ while specifying the precision & number of decimal digits?

For example: 3.14159265359 -> "3.14"


Solution 1:

A typical way would be to use stringstream:

#include <iomanip>
#include <sstream>

double pi = 3.14159265359;
std::stringstream stream;
stream << std::fixed << std::setprecision(2) << pi;
std::string s = stream.str();

See fixed

Use fixed floating-point notation

Sets the floatfield format flag for the str stream to fixed.

When floatfield is set to fixed, floating-point values are written using fixed-point notation: the value is represented with exactly as many digits in the decimal part as specified by the precision field (precision) and with no exponent part.

and setprecision.


For conversions of technical purpose, like storing data in XML or JSON file, C++17 defines to_chars family of functions.

Assuming a compliant compiler (which we lack at the time of writing), something like this can be considered:

#include <array>
#include <charconv>

double pi = 3.14159265359;
std::array<char, 128> buffer;
auto [ptr, ec] = std::to_chars(buffer.data(), buffer.data() + buffer.size(), pi,
                               std::chars_format::fixed, 2);
if (ec == std::errc{}) {
    std::string s(buffer.data(), ptr);
    // ....
}
else {
    // error handling
}

Solution 2:

The customary method for doing this sort of thing is to "print to string". In C++ that means using std::stringstream something like:

std::stringstream ss;
ss << std::fixed << std::setprecision(2) << number;
std::string mystring = ss.str();

Solution 3:

You can use C++20 std::format:

#include <format>

int main() {
  std::string s = std::format("{:.2f}", 3.14159265359); // s == "3.14"
}

or the fmt::format function from the {fmt} library, std::format is based on (godbolt):

#include <fmt/core.h>

int main() {
  std::string s = fmt::format("{:.2f}", 3.14159265359); // s == "3.14"
}

where 2 is a precision.

It is not only shorter than using iostreams or sprintf but also significantly faster and is not affected by the locale.