Domanda

I'm reading from a CSV, line by line and tokenizing each comma separated value. each token is a string type. and I'm putting it into a vector of type float. In the example below, if for example if the value in the csv is "0.08" , *beg = "0.08" , but in vector v it is "0.079999998"

Is there someway that I can set the precision in the vector to 3 decimal places or something.

example:

string line;
boost::char_separator<char> sep(",");
typedef boost::tokenizer< boost::char_separator<char> > t_tokenizer;
ifstream myfile (fileName);

if(myfile.is_open())
{
    while (myfile.good())
    {
        getline (myfile,line);
        t_tokenizer tok(line, sep);

        for (t_tokenizer::iterator beg = tok.begin(); beg != tok.end(); ++beg)
        {
             string temp = *beg;
             this->v.push_back(::atof(temp.c_str()));
        }
È stato utile?

Soluzione

You are using atof, which implies you're using float to hold the data. Floating point values do not hold base-10 values as accurately as you might expect. So simple numbers like this may not have a good binary representation.

You have a couple options:

  1. Deal with imprecision properly. You must always be aware of precision when dealing with floating point, so if you want to display that number to the nearest 2 decimal places, do the proper rounding and it will always work like you want.

  2. Use integers only. If you only ever need 2 digits of precision after the decimal point, just store the values as int which are multiplied by 100. So 0.08 is stored as 8. Write your own functions to parse directly into this format.

Altri suggerimenti

This isn't a problem with the float. You cannot represent 0.8 exactly, but no worries -- simply output the values with the desired precision:

#include <iomanip>   // for fixed and setprecision
#include <iostream>  // for cout
#include <cstdio>    // for printf

for (auto it = v.cbegin(), end = v.cend(); it != end; ++it)
{
  std::cout << std::fixed << std::setprecision(3) << *it << std::endl;
}

Alternatively, you can use std::printf("%.3f\n", *it).

If you truly want to store exact values in your data structure, you cannot use normal floats. You can either use some sort of fixed-point interpretation of integers (e.g. measure everything in units of 1/1000), or you can use decimal floats (rare), or you can store rational numbers (quotients of integers). If you only do addition and subtraction, fixed-point would be the natural way to go.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top