set precision when push_back on Vector
質問
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()));
}
解決
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:
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.
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. So0.08
is stored as8
. Write your own functions to parse directly into this format.
他のヒント
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.