Given the following code :
istringstream i("2.11099999999999999999");
double d;
if (!(i >> d)) {d = 0;}
cout << d << endl;
The output is 2.111
.
I want to have the ability of working with long numbers , float numbers (floating point included) , however when I convert my istringstream
to double , I get a rounded number .
How can I prevent that ? How can I keep the given input as-is ?
Regards
In this case, you can't prevent it. double
is not capable of precisely representing the value 2.11099999999999999999, and none of the values it can represent distinguishes 2.11099999999999999999 from 2.111.
http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html should tell you what you need to know, and possibly more.
If you use a different example, where double
can represent values that distinguish between the rounded and unrounded value, then you could do this:
#include <iostream>
#include <sstream>
#include <iomanip>
int main() {
std::istringstream iss("2.1109999");
double d;
iss >> d;
std::cout << d << "\n";
std::cout << std::setprecision(10) << d << "\n";
}
Output:
2.111
2.1109999
You should be aware, though, that the value stored in d
is not exactly 2.1109999
:
std::cout << std::setprecision(20) << d << "\n";
Output (on my machine, yours may differ because some runtime libraries don't print to 20 s.f at all):
2.1109998999999999292
That's because double
stores values in binary, not decimal. So it can only represent terminating binary fractions. 2.1109999 is not a terminating binary fraction for basically the same reason that one third is not a terminating decimal fraction.
So, there are two ways to keep the given input as-is (i.e. to represent that number precisely):
double
, leave it as a string.double
, instead find or write a library that represents decimal fractions and/or rational numbers. For example, the GMP library has mpq_t
or there's Boost.Rational.