Установить точность при push_back на Vector

Я читаю из CSV, построчно и разбиваю каждое значение через запятую. каждый токен является строковым типом. и я помещаю его в вектор типа float. В приведенном ниже примере, например, если значение в csv равно "0.08", *beg = "0.08", но в векторе v это "0.079999998"

Есть ли что-то, что я могу установить точность в векторе до 3 десятичных знаков или что-то еще.

пример:

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()));
        }

2 ответа

Решение

Ты используешь atof, что подразумевает, что вы используете float держать данные. Значения с плавающей точкой не содержат значения base-10 так точно, как вы могли бы ожидать. Такие простые числа, как это, могут не иметь хорошего двоичного представления.

У вас есть пара вариантов:

  1. Справиться с неточностью правильно. Вы должны всегда помнить о точности при работе с плавающей точкой, поэтому, если вы хотите отобразить это число с точностью до 2 десятичных знаков, выполните правильное округление, и оно всегда будет работать так, как вы хотите.

  2. Используйте только целые числа. Если вам нужно только 2 цифры точности после десятичной точки, просто сохраните значения как int которые умножаются на 100. Так 0.08 хранится как 8, Напишите свои собственные функции для анализа непосредственно в этот формат.

Это не проблема с поплавком. Вы не можете точно представить 0,8, но не беспокойтесь - просто выведите значения с желаемой точностью:

#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;
}

Кроме того, вы можете использовать std::printf("%.3f\n", *it),

Если вы действительно хотите хранить точные значения в вашей структуре данных, вы не можете использовать обычные числа с плавающей точкой. Вы можете использовать некоторую интерпретацию целых чисел с фиксированной запятой (например, измерять все в единицах от 1/1000), либо использовать десятичные числа с плавающей запятой (редко), либо вы можете хранить рациональные числа (коэффициенты целых чисел). Если вы делаете только сложение и вычитание, естественным путем будет фиксированная точка.

Другие вопросы по тегам