Set Precision of Std::To_String When Converting Floating Point Values

Set precision of std::to_string when converting floating point values

There is no way to change the precision via to_string() but the setprecision IO manipulator could be used instead:

#include <sstream>

template <typename T>
std::string to_string_with_precision(const T a_value, const int n = 6)
{
std::ostringstream out;
out.precision(n);
out << std::fixed << a_value;
return out.str();
}

The precision of std::to_string(double)

No.


Returns: Each function returns a string object holding the character representation of the value of
its argument that would be generated by calling sprintf(buf, fmt, val) with a format specifier of
"%d", "%u", "%ld", "%lu", "%lld", "%llu", "%f", "%f", or "%Lf", respectively, where buf designates
an internal character buffer of sufficient size.

How to use std::to_string function to format float as “x.0”

std::to_string doesn't support this, and in fact is not generally great for arbitrary floating-point values.

Since your question is tagged c++11, there are two ways I'm aware of. Firstly, you have std::stringstream, which is type safe and will work with arbitrary types:

#include <sstream>

// ...

float number = 30.0f;

std::ostringstream oss;
oss << std::setprecision(1) << number;
std::string result = oss.str();

Alternatively, you have std::snprintf, which requires converting through a char buffer of a given size:

float number = 30.0f;

char buffer[20]; // maximum expected length of the float
std::snprintf(buffer, 20, "%.1f", number);
std::string str(buffer);

From C++17 you may use std::to_chars instead in a similar way to std::snprintf, and from C++20 you may use std::format.

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

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
}

How to avoid `std::to_string()` making a very small double number to 0?

No, the problem is not precision, but the format. You want to print in scientific format (with exponent) but std::to_string() uses the fixed format by default and I'm not aware of any way to change this.

However, streams use scientific if appropriate or you can force it with std::scientific:

std::ostringstream oss;
oss << 4.7816457028269855e-143;
std::string numberAsString = oss.str(); // stores "4.78165e-143"

Of course you can increae the precision in addition to this.

If for whatever reason you don't want to use scientific format, you can use the fixed format with a high enough precision. "High enough" meaning more than 142 in this case, because there will be 142 leading zeroes:

oss << std::fixed << std::setprecision(142 + x);

But the scientific format is better suited, I guess.

Is std::to_string guaranteed to include a decimal point when converting floating point values?

to_string seems to always return a string containing a decimal point followed by six digits. Is this behavior guaranteed (excluding nan and infinity)?

Yes. The output of std::to_string is controlled by the output std::sprintf, whose default precision is 6.

From http://en.cppreference.com/w/cpp/string/basic_string/to_string,

7,8) Converts a floating point value to a string with the same content as what std::sprintf(buf, "%f", value) would produce for sufficiently large buf.

From http://en.cppreference.com/w/cpp/io/c/fprintf, (emphasis mine)

f, F

converts floating-point number to the decimal notation in the style [-]ddd.ddd.

Precision specifies the minimum number of digits to appear after the decimal point character. The default precision is 6.



Caveat

The decimal point is not used as the decimal marker in all locales. You might get a different character for the decimal marker depending on the locale. But a decimal marker will be there regardless of locale.

Convert float to std::string without losing precision. Also I don't want to use sprintf

I suggest you call snprintf with format specifier "%.16g" - that prints a double in decimal with 16 significant digits of precision. See Number of Digits Required For Round-Trip Conversions for more details. E.g.:

inline std::string as_string(double value) {
char buf[32];
return std::string(buf, std::snprintf(buf, sizeof buf, "%.16g", value));
}

*printf functions are fundamental conversion routines, everything else uses these.

std::to_string in GNU C++ standard library does:

inline string to_string(double __val)  {
const int __n = __gnu_cxx::__numeric_traits<double>::__max_exponent10 + 20;
return __gnu_cxx::__to_xstring<string>(&std::vsnprintf, __n, "%f", __val);
}

std::ostream also calls *snprintf under the hood to format numbers.


Also note that 3.14159267 is double. A float constant requires f suffix, e.g. 3.14159267f.

Loss of Precision when Converting Double to String in C++

You can use std::stringstream.

#include <iostream>
#include <sstream>
#include <iomanip>
using namespace std;

int main(void) {
double var = 1.0000001;
cout << setprecision(10)<< var << endl;
stringstream ss;
ss << setprecision(10) << var;
string str;
ss >> str;
cout << str << endl;
return 0;
}


Related Topics



Leave a reply



Submit