конвертация строки в double
От: Alezis  
Дата: 27.05.10 07:49
Оценка:
Всем привет.
Столкнулся с такой проблемой. Есть файл c вещественными числами. Файлы текстовые и соответсвенно число тоже представлено текстом.
Причем это число может быть и "0.000000000001" и "1.E-12". В итоге когда я читаю файл и конвертирую
istrstream istr( str.c_str(), str.size() );
istr >> number;

в double, а затем сравниваю два дабла то иногда сравнение не правильное.
Я знаю что double не резиновый, но мне важен результат сравнения двух эквивалентных величин полученных из текстовЫХ файлОВ.
Грубо говоря если поведение будет одинаково для любого формата строки которую я прочитал из файла, то как оно там представлено в double не столь важно, но на деле сравнение не правильное.
Получается что программа при сравнении дает неверные результаты, потому что если взять и конвертировать "0.000000000001" и "1.E-12" через istrstream и затем сравнить эти два числа то получится неверный результат сравнения. По крайней мере на VS2005 SP1.
Тоже самое справедливо и для istringstream. А вот если использовать strtod и atof то все нормально (имеется ввиду результат сравнения). Получается что в моем случае стоит использовать именно последние 2 функции.
Самое интерестное что вывод double в cout всегда корректен и дает 1.e-012 или что то эквивалентное.
На других компиляторах тоже самое ?
#include <string>
#include <strstream>
#include <sstream>
#include <istream>
#include <iostream>
#include <conio.h>

int compare_str_str__istrstream(std::string sDouble1, std::string sDouble2); 
int compare_str_str__strtod(std::string sDouble1, std::string sDouble2); 
int compare_str_str__atof(std::string sDouble1, std::string sDouble2); 
int compare_double_str__istrstream(double sDouble1, std::string sDouble2); 
int compare_double_str__strtod(double double1, std::string sDouble2);
int compare_double_str__atof(double double1, std::string sDouble2);
int compare_double_str__istringstream(double double1, std::string sDouble2); 
int compareDouble( double double1, double double2 );
void test_str_str(std::string sDouble1, std::string sDouble2);
void test_double_str(double double1, std::string sDouble2);


int main(int argc, char* argv[])
{
   
  test_str_str("0.000000000001","1.E-12");
  test_str_str("0.000000000001E-0","1.E-12");
  test_str_str("1.00E-12","1.E-12");
 
  test_double_str(0.000000000001,"1.E-12");
  test_double_str(0.000000000001E-0,"1.E-12");
  test_double_str(0.000000000001,"0.000000000001");
  test_double_str(1.E-12,"0.000000000001");

 _getch();
    return 0;
}

void test_str_str(std::string sDouble1, std::string sDouble2)
{
  std::cout << "--------------------------------------------------------------" <<std::endl;
  std::cout << "compare: " << sDouble1.c_str() << " vs " << sDouble2.c_str() <<std::endl;
  std::cout << "compare_str_str__istrstream: " << compare_str_str__istrstream(sDouble1,sDouble2) <<std::endl;
  std::cout << "compare_str_str__strtod: " << compare_str_str__strtod(sDouble1,sDouble2) <<std::endl;
  std::cout << "compare_str_str__atof: " << compare_str_str__atof(sDouble1,sDouble2) <<std::endl;
  std::cout <<std::endl;
}

void test_double_str(double double1, std::string sDouble2)
{
  std::cout << "--------------------------------------------------------------" <<std::endl;
  std::cout << "compare: " << double1 << " vs " << sDouble2.c_str() <<std::endl;
  std::cout << "compare_double_str__istrstream: " << compare_double_str__istrstream(double1,sDouble2) <<std::endl;
  std::cout << "compare_double_str__istringstream: " << compare_double_str__istringstream(double1,sDouble2) <<std::endl;
  std::cout << "compare_double_str__strtod: " << compare_double_str__strtod(double1,sDouble2) <<std::endl;
  std::cout << "compare_double_str__atof: " << compare_double_str__atof(double1,sDouble2) <<std::endl;
  std::cout <<std::endl;
}

int compare_str_str__istrstream(std::string sDouble1, std::string sDouble2) 
{
  double double1;
  std::istrstream istr1( sDouble1.c_str(), (int)sDouble1.size() );
  istr1 >> double1;

  double double2;
  std::istrstream istr2( sDouble2.c_str(), (int)sDouble2.size() );
  istr2 >> double2;
  return compareDouble(double1, double2);
}

int compare_str_str__strtod(std::string sDouble1, std::string sDouble2)
{
  double double1 = strtod(sDouble1.c_str(),NULL);
  double double2 = strtod(sDouble1.c_str(),NULL);
  return compareDouble(double1, double2);
}

int compare_str_str__atof(std::string sDouble1, std::string sDouble2)
{
  double double1 = atof(sDouble1.c_str());
  double double2 = atof(sDouble1.c_str());
  return compareDouble(double1, double2);
}


int compare_double_str__istringstream(double double1, std::string sDouble2) 
{
  double double2;
  std::istringstream istr( sDouble2 );
  istr >> double2;
  return compareDouble(double1, double2);
}

int compare_double_str__istrstream(double double1, std::string sDouble2) 
{
  double double2;
  std::istrstream istr( sDouble2.c_str(), (int)sDouble2.size() );
  istr >> double2;
  return compareDouble(double1, double2);
}

int compare_double_str__strtod(double double1, std::string sDouble2)
{
  double double2 = strtod(sDouble2.c_str(),NULL);
  return compareDouble(double1, double2);
}

int compareDouble( double double1, double double2 );
int compare_double_str__atof(double double1, std::string sDouble2)
{
  double double2 = atof(sDouble2.c_str());
  return compareDouble(double1, double2);
}

int compareDouble( double double1, double double2 )
{
  if(double1 > double2)
    return  1;
  else
    if (double2 > double1 )
    {
      return -1;
    }
    return 0;
}


Результаты VS2005 SP1
--------------------------------------------------------------
compare: 0.000000000001 vs 1.E-12
compare_str_str__istrstream: 1
compare_str_str__strtod: 0
compare_str_str__atof: 0

--------------------------------------------------------------
compare: 0.000000000001E-0 vs 1.E-12
compare_str_str__istrstream: 1
compare_str_str__strtod: 0
compare_str_str__atof: 0

--------------------------------------------------------------
compare: 1.00E-12 vs 1.E-12
compare_str_str__istrstream: 0
compare_str_str__strtod: 0
compare_str_str__atof: 0

--------------------------------------------------------------
compare: 1e-012 vs 1.E-12
compare_double_str__istrstream: 0
compare_double_str__istringstream: 0
compare_double_str__strtod: 0
compare_double_str__atof: 0

--------------------------------------------------------------
compare: 1e-012 vs 1.E-12
compare_double_str__istrstream: 0
compare_double_str__istringstream: 0
compare_double_str__strtod: 0
compare_double_str__atof: 0

--------------------------------------------------------------
compare: 1e-012 vs 0.000000000001
compare_double_str__istrstream: -1
compare_double_str__istringstream: -1
compare_double_str__strtod: 0
compare_double_str__atof: 0

--------------------------------------------------------------
compare: 1e-012 vs 0.000000000001
compare_double_str__istrstream: -1
compare_double_str__istringstream: -1
compare_double_str__strtod: 0
compare_double_str__atof: 0
convert double istrstream
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.