2

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?

Community
  • 1
  • 1
akash_c
  • 173
  • 1
  • 2
  • 9
  • Thry this: `cout << a << " " << b << " " << c << endl;` – juanchopanza Aug 08 '13 at 08:45
  • @juanchopanza No help and it is rounding up the values not truncating them the output from your suggestion `9292.31 4234.66 342.254 32432.2 3423.66 341.678` – akash_c Aug 08 '13 at 08:50
  • Note that the sentence `file.close()` sentence is not needed. The stream closes the file at the end of its lifetime. Read about RAII: http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization – Manu343726 Aug 08 '13 at 08:52
  • +1 Noobie C++ code without C-style io. Only C++. Well done. – Manu343726 Aug 08 '13 at 08:54
  • Well, you didn't clearly say what the problem was. You should state the issue more clearly. – juanchopanza Aug 08 '13 at 08:54
  • @Manu343726 On the other hand, it doesn't hurt (and you do have to explicitly close output, because you have to check its status after the close). – James Kanze Aug 08 '13 at 09:18
  • I might mention that the test `file.good()` in the `while` isn't necessary. If that condition is false, `getline` (and every other input operation) is a no-op, and returns false. – James Kanze Aug 08 '13 at 09:19
  • You should drop the `#include ` and use `#include ` instead. – Kyle_the_hacker Aug 08 '13 at 09:20

4 Answers4

2

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

0

This is a problem in the precision of the cout. Try to test the comparison:

cout << "Stand.: " << a << "  Prec.: " << fixed << setprecision(10) << a << endl;
Kyle_the_hacker
  • 1,394
  • 1
  • 11
  • 27
0

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++. ;-)

jtuki
  • 385
  • 1
  • 5
  • 8
0

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.

James Kanze
  • 150,581
  • 18
  • 184
  • 329
  • explicit cast to integer is generally known as a truncating conversion. –  Aug 08 '13 at 09:51
  • @Frodo Yes, but it's a conversion. The double itself isn't changed. (But I can see that my wording might be ambiguous here.) – James Kanze Aug 08 '13 at 09:59
  • `You can't truncate a double.` Actually, you _can_ trucate the value contained within a IEEE `double` or `float`. See [Loss of significance](http://en.wikipedia.org/wiki/Loss_of_significance) for more information on the subject. –  Aug 09 '13 at 10:21