double value = 02369.000133699;//acutally stored as 2369.000133698999900
const std::uint32_t left = std::uint32_t(std::abs(value) < 1 ? 1: (1 + std::log10(std::abs(value))));
std::ostringstream out;
out << std::setprecision(std::numeric_limits<T>::digits10 - left ) << std::fixed << value;
std::string str = out.str(); //str = "2369.00013369900"
std::ostringstream out2;
out2 << std::setprecision(std::numeric_limits<T>::digits10 ) << std::fixed << value;
std::string str2 = out2.str(); // str2 = "2369.000133698999900"
I'm wondering how std::stringstream/precision works for formatting floating-point number.
It seems that if precision argument is superior to 16
minus number of non-fractional digits, this lead to a formatting of form "2369.000133698999900"
instead of a "nice" "2369.00013369900"
how std::stringstream
know that 8999900
must be resume to one 9
even if I don"t tell it to do the rounding on the 8
(like passing 12
as argument to the setprecision
function) ?but don't do it for argument superior to 12
Formatting binary floating points as decimal values is fairly tricky. The underlying problem is that binary floating points cannot represent decimal values accurately. Even a simple number like 0.1 cannot be represented exactly using binary floating points. That is, the actual value represented is slightly different. When using clever algorithms for reading ("Bellerophon") and formatting ("Dragon4"; these are the names from the original papers and there are improvements of both algorithms which are used in practice) floating point numbers be used to transport decimal values. However, when asking the algorithm to format more decimal digits than it can actually hold, i.e., more than std::numeric_limits<T>::digits10
, it will happily do so, [partially] revealing the value it is actually storing.
The formatting algorithm ("Dragon4") assumes that the value it is given is the value closest to the original representable with the floating point type. It uses this information together with an error estimate for the current position to determine the correct digits. The algorithm itself is non-trivial and I haven't fully understood how it works. It is described in the paper "How to Print Floating-Point Numbers Accurately" by Guy L. Steele Jr. and Jon L. White.