Nano Hash - криптовалюты, майнинг, программирование

Как читать float с экспоненциальной нотацией из файла C++?

У меня есть файл такого формата:

-0.0064785667 0.73900002 0.028505694 4.7858757e-39 315 218
-0.0051828534 0.73900002 0.028505694 4.6936954e-39 316 218
-0.0038818798 0.73799998 0.028467119 5.1546736e-39 317 218
-0.0025879198 0.73799998 0.028467119 5.6160217e-39 318 218
-0.0012939599 0.73799998 0.028467119 6.4461411e-39 319 218

Я прочитал это с этим кодом:

using namespace std;   

ifstream inputFile;

//Opens data file for reading.
inputFile.open(filePath.c_str());

//Creates vector, initially with 0 points.
vector<Point> data(0);
float temp_x,temp_y,temp_z,rgb=0,discard_1=0,discard_2=0;

//Read contents of file till EOF.
while (inputFile.good()){

    inputFile >> temp_x >> temp_y >> temp_z >> rgb >> discard_1 >> discard_2;

    data.push_back(Point(temp_x,temp_y,temp_z,rgb));

}

if (!inputFile.eof())
    if (inputFile.fail()) cout << "Type mismatch during parsing." << endl;
    else cout << "Unknow problem during parsing." << endl;

//Close data file.
inputFile.close();

Чтение научной нотации с плавающей запятой приводит к несоответствию типов.

Как я могу прочитать все числа, включая число с плавающей запятой?


  • Вы пытались объявить переменные двойными? 24.01.2012
  • Я не могу воспроизвести эту ошибку. Можете ли вы предоставить полную программу, которая показывает ошибку (в идеале, изменив пример, который я опубликовал)? 24.01.2012
  • Пробовал объявить rgb как double и работает. Но я хотел бы иметь возможность читать поплавок напрямую... 24.01.2012
  • Вы получаете состояние отказа, если пытаетесь прочитать число с плавающей запятой, превышающее максимальное число с плавающей запятой (около 3,40E38). Это не относится к значениям, которые вы показываете здесь (они должны читаться как 0 в вещественном числе), но это может объяснить, почему это работает с двойным, а не с плавающим числом. 24.01.2012

Ответы:


1

Проблема, вероятно, в вашем цикле while. Никогда не используйте while(inputFile.good()). Использовать этот:

while (inputFile >> temp_x >> temp_y >> temp_z 
                 >> rgb >> discard_1 >> discard_2) {}

Этот ответ на другой вопрос объясняет, почему. Вас также может заинтересовать этот ответ, который предлагает более элегантное решение.

24.01.2012
  • Разместил полный код, я попробую ваше исправление и посмотрю, работает ли оно. 24.01.2012
  • @Luis: Глядя на ваш код, я думаю, вы могли бы подойти к этой проблеме по-другому, как описано во второй ссылке в моем ответе. 24.01.2012
  • @Luis: Что именно происходит? Можете ли вы привести полный пример? Знаете ли вы, что ваша программа будет печатать "Type mismatch during parsing.", даже если все работает нормально? 24.01.2012
  • Извините, исправил оператор else, если он достигнет EOF, он не выведет никакого сообщения об ошибке. Только если он не попадает в EOF, печатает сообщения об ошибках. 24.01.2012
  • В вашей второй ссылке, как бы вы отбросили то, что вам не нужно для класса, например discard_1 и 2? 24.01.2012
  • Хороший вопрос. Я уверен. Вы можете сделать это непосредственно в операторе извлечения для Point, прочитав их в фиктивную ложь, которую вы сделали в своем коде (хотя вам нужна только одна фиктивная переменная). Это, конечно, проблематично, если вы хотите, чтобы Point работал с файлами разных форматов. В этом случае, я думаю, вы могли бы написать класс PointAdapter, который имеет неявное приведение к Point и оператор извлечения, который может читать определенный формат файла. Я добавлю предложение к моему ответу. 24.01.2012
  • +1, структура цикла неверна, независимо от того, есть ли другая проблема или нет. 24.01.2012
  • @Luis: Это сложнее, чем я, дай мне немного времени. 24.01.2012
  • Что именно происходит с float rgb, так это то, что он перестает читать файл после значения z, давая несоответствие типа, как если бы он не распознавал научную нотацию, с обычным float, то есть без научной нотации, он работает. Даже при изменении условия цикла единственным решением является объявление rgb двойным... 24.01.2012

  • 2

    Расширение ответа Бьорна Поллекса с примером без обработки ошибок:

    #include <iostream>
    #include <fstream>
    #include <iterator>
    #include <vector>
    
    struct point
    {
        double x, y, z, rgb;
    };
    
    struct point_line: public point
    {
        int discard[2];
    };
    
    std::istream& operator >>(std::istream& is, point_line& in)
    {
        is >> in.x >> in.y >> in.z >> in.rgb >> in.discard[0] >> in.discard[1];
        // TODO: Add your error-handlin
    
        return is;
    }
    
    std::ostream& operator <<(std::ostream& os, const point& out)
    {
        os << " X: " << out.x
           << " Y: " << out.y
           << " Z: " << out.z
           << " RGB: " << out.rgb
           ;
    
        return os;
    }
    
    int main()
    {
        std::ifstream points_file("points.txt");
        std::vector<point> points;
        std::copy(std::istream_iterator<point_line>(points_file),
                  std::istream_iterator<point_line>(),
                  std::back_inserter(points));
    
        std::copy(points.begin(),
                  points.end(),
                  std::ostream_iterator<point>(std::cout, "\n"));
    }
    
    24.01.2012
  • Это первый раз, когда я вижу нарезку как преднамеренный и полезный эффект. Хотя интересно - это разрешено? Может ли это привести к утечке памяти? Я не уверен. 24.01.2012
  • Я думаю, что впервые использую его таким образом :-) Это, безусловно, работает, и point_line будут уничтожены после того, как они будут нарезаны на vector, так что я не думаю, что есть утечка памяти. Возможно, мне следует задать это как вопрос... 24.01.2012
  • Хотя, если подумать, я не думаю, что есть проблема с памятью. Он просто вызовет конструктор копирования point со ссылкой на point_line, что совершенно нормально. 24.01.2012
  • @BjörnPollex: Да, это была моя мысль. 24.01.2012
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..