Reputation: 173
I am trying to get float values out of a file to use them in my program. I used the following forum to construct the program Read file line by line.
But the values obtained by doing so appear to be truncated at the end.
My code
#include <iostream>
#include <cstring>
#include <sstream>
#include <fstream>
using namespace std;
int main()
{
ifstream file;
file.open("test_file.ssv");
string line;
while(file.good() && (getline(file, line)))
{
istringstream iss(line);
double a, b, c;
iss >> a >> b >>c ;
cout << a <<endl;
}
file.close();
return (0);
}
The output that I obtain is
9292.31
32432.2
While my file has the following data
9292.3123 4234.66 342.25423
32432.2423 3423.656 341.67841
Any suggestions to improve upon this?
Upvotes: 2
Views: 3569
Reputation:
Your standard stream may have a low floating point precision and you therefore only see a few of the decimals when outputing a float
with std::cout
. Use std::ios_base::precision
to increase the precision and look into using std:: ios::floatfield
to output fixed or scientific precision , example:
// modify precision
#include <iostream> // std::cout, std::ios
int main () {
double f = 3.14159;
std::cout.unsetf ( std::ios::floatfield ); // floatfield not set
std::cout.precision(5);
std::cout << f << '\n';
std::cout.precision(10);
std::cout << f << '\n';
std::cout.setf( std::ios::fixed, std:: ios::floatfield ); // floatfield set to fixed
std::cout << f << '\n';
return 0;
}
Outputs:
3.1416 3.14159 3.1415900000
Upvotes: 2
Reputation: 153899
Nothing has been truncated. You can't truncate a double
; it
always has the same number of bits and the same format. But
you're outputting using the default precision (6) and the
default format, which will always output 6 significant digits,
and no more.
There are two issues here. The first is simple: what format and precision do you want? There are three possible formats: the default (which will use either fixed or scientific, depending on the value, and for which the precision signifies the maximun number of significant digits), fixed , or scientific (where the precision signifies the number of digits after the decimal). Thus, with a precision of 6, depending on the format, your first value will be:
default: 9292.31
fixed: 9292.312300
scientific: 9.292312E03
For the values you show, fixed would seem most appropriate; but if you have very small values, it will display less digits, and for very large values, you can get some very long strings.
The usual way of handling this is to define a manipulator for
whatever the values represent; in this case, I'll just call it
values
, because I don't know anything more precise about your
application, but you should probably find a more meaningful
name:
class value
{
mutable std::ostream* myOwner;
mutable std::ios_base::fmtflags myFlags;
mutable int myPrecision;
void capture( std::ostream& owner )
{
if ( myOwner == NULL ) {
myOwner = &owner;
myFlags = myOwner->fmtflags();
myPrecision= myOwner->precision();
}
}
public:
value() : myOwner( NULL ) {}
~value()
{
if ( myOwner != NULL ) {
myOwner->flags( myFlags );
myOwner->precision( myPrecision );
}
}
friend std::ostream& operator<<( std::ostream& dest, value const& manip )
{
manip.capture( dest );
dest.setf( std::ios_base::fixed, std::ios_base::floatfield );
dest.precision( 6 );
}
};
This will also restore the formatting status at the end of the full expression (since it should only be used as a temporary); this is generally a good idea becaues it prevents surprises in later code. If you're doing any significant output, you'll create a base class for the save and restore, and derive your actual manipulator from that.
Once you have this, you can write:
std::cout << value() << a << " " << b << " " << c << std::endl;
All of the values after value()
in the statement will be
output with the desired format.
More generally, do you understand how machine floating point works? The actual values stored in your doubles will not be those that you see in the file, because those that you see in the file are not representable in the usual double format. For the number of digits you enter, you should not see any difference if you output the same number of digits, or even one or two more, but if you output a very large number of digits (say about 17) you could.
Upvotes: 0
Reputation: 415
Use the code below will make some improvement.
std::cout << std::setprecision(10) << a << std::endl;
Reference to the two links below for more information:
http://www.cplusplus.com/reference/ios/ios_base/precision/
http://www.cplusplus.com/reference/iomanip/setprecision/
Happy coding with C++. ;-)
Upvotes: 0
Reputation: 1434
This is a problem in the precision of the cout
.
Try to test the comparison:
cout << "Stand.: " << a << " Prec.: " << fixed << setprecision(10) << a << endl;
Upvotes: 0