The Precision of Std::To_String(Double)

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.

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.

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;
}

C++11 std::to_string(double) - No trailing zeros

The C++11 Standard explicitely says (21.5/7):

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

for the functions declared in this order:

string to_string(int val);
string to_string(unsigned val);
string to_string(long val);
string to_string(unsigned long val);
string to_string(long 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);

Thus, you cannot control the formatting of the resulting string.

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.

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
}

double to std::string with dynamic precisicion (without trailing zeros)

You can use string stream (sstring) with stream manipulators, see example below:

  std::stringstream ss1;
std::stringstream ss2;
ss1.precision(15);
ss1 << 3.14;
std::cout << ss1.str()<<' '<<("3.14" == ss1.str())<<std::endl;
ss2.precision(15);
ss2 << 3.1415926536;
std::cout << ss2.str()<<' '<<("3.1415926536" == ss2.str())<<std::endl;

Or you can use boost format. Here's a link!

  std::cout<<format("%.2f") % 3.14 <<std::endl;
std::cout<<format("%.10f") % 3.1415926536 <<std::endl;


Related Topics



Leave a reply



Submit