double and stringstream formatting
For anyone who gets "error: ‘setprecision’ is not a member of ‘std’
" you must #include <iomanip>
else setprecision(17)
will not work!
You can change the floating-point precision of a stringstream
as follows:
double num = 2.25149;
std::stringstream ss(stringstream::in | stringstream::out);
ss << std::setprecision(5) << num << endl;
ss << std::setprecision(4) << num << endl;
Output:
2.2515
2.251
Note how the numbers are also rounded when appropriate.
There are two issues you have to consider. The first is the precision
parameter, which defaults to 6 (but which you can set to whatever you
like). The second is what this parameter means, and that depends on the
format option you are using: if you are using fixed or scientific
format, then it means the number of digits after the decimal (which in
turn has a different effect on what is usually meant by precision in the
two formats); if you are using the default precision, however (ss.setf(
std::ios_base::fmtflags(), std::ios_base::formatfield )
, it means the
number of digits in the output, regardless of whether the output was
actually formatted using scientific or fixed notation. This explains
why your display is 12.1231
, for example; you're using both the
default precision and the default formattting.
You might want to try the following with different values (and maybe different precisions):
std::cout.setf( std::ios_base::fmtflags(), std::ios_base::floatfield );
std::cout << "default: " << value[i] << std::endl;
std::cout.setf( std::ios_base::fixed, std::ios_base::floatfield );
std::cout << "fixed: " << value[i] << std::endl;
std::cout.setf( std::ios_base::scientific, std::ios_base::floatfield );
std::cout << "scientific: " << value[i] << std::endl;
Seeing the actual output will probably be clearer than any detailed description:
default: 0.1
fixed: 0.100000
scientific: 1.000000e-01
The problem occurs at the stream insertion ss << 0.1;
rather than at the conversion to string. If you want non-default precision you need to specify this prior to inserting the double:
ss << std::setprecision(17) << val;
On my computer, if I just use setprecision(16)
I still get "0.1"
rather than "0.10000000000000001"
. I need a (slightly bogus) precision of 17 to see that final 1.
Addendum
A better demonstration arises with a value of 1.0/3.0. With the default precision you get a string representation of "0.333333"
. This is not the string equivalent of a double precision 1/3. Using setprecision(16)
makes the string "0.3333333333333333"
; a precision of 17 yields "0.33333333333333331"
.