Re: конвертация строки в double
От: Bell Россия  
Дата: 27.05.10 08:02
Оценка: 1 (1)
Здравствуйте, Alezis, Вы писали:

...
A>На других компиляторах тоже самое ?

http://codepad.org/ выдает везде одинаковые результаты.

Совсем недавно давал ссылки по теме: здесь
Автор: Bell
Дата: 25.05.10
Любите книгу — источник знаний (с) М.Горький
Re[4]: конвертация строки в double
От: Erop Россия  
Дата: 27.05.10 11:46
Оценка: +1
Здравствуйте, Pavel Dvorkin, Вы писали:

E>>Только это епс должно быть относительной погрешностью, а не абсолютной


PD>В теории — да. Практически — если известен диапазон допустимых значений и он узкий, то можно и абсолютную взять.



Ну ты его примеры видел?
Кроме того, если диапазон реально узкий, то лучше взять int64...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
конвертация строки в 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
Re[2]: конвертация строки в double
От: Alezis  
Дата: 27.05.10 08:07
Оценка:
Здравствуйте, Bell, Вы писали:

B>Здравствуйте, Alezis, Вы писали:


B>...

A>>На других компиляторах тоже самое ?

B>http://codepad.org/ выдает везде одинаковые результаты.


B>Совсем недавно давал ссылки по теме: здесь
Автор: Bell
Дата: 25.05.10

Спасибо за ссылки.
Re: конвертация строки в double
От: Sni4ok  
Дата: 27.05.10 09:39
Оценка:
Здравствуйте, Alezis, Вы писали:


A>Я знаю что double не резиновый, но мне важен результат сравнения двух эквивалентных величин полученных из текстовЫХ файлОВ.


даже если два дабла бинарно идентичны, они не обязаны быть равны, как пример — NAN.
Re[2]: конвертация строки в double
От: Alezis  
Дата: 27.05.10 09:47
Оценка:
Здравствуйте, Sni4ok, Вы писали:

S>Здравствуйте, Alezis, Вы писали:



A>>Я знаю что double не резиновый, но мне важен результат сравнения двух эквивалентных величин полученных из текстовЫХ файлОВ.


S>даже если два дабла бинарно идентичны, они не обязаны быть равны, как пример — NAN.

Мне важны чтобы разные представления числа из текстового файла давали на выходе алгоритма одни и те же результаты, а конкретно индекс в массиве. Под эквивалентными я подразумеваю разное текстовое представление числа. например 0,001 и 1e-3.И все.
Re: конвертация строки в double
От: Pavel Dvorkin Россия  
Дата: 27.05.10 10:20
Оценка:
Здравствуйте, Alezis, Вы писали:

A>int compareDouble( double double1, double double2 )

A>{
A> if(double1 > double2)
A> return 1;
A> else
A> if (double2 > double1 )
A> {
A> return -1;
A> }
A> return 0;
A>}
A>[/ccode]

Все правильно.

Вот в этой функции при вызове из

1.exe!compare_str_str__istrstream(std::basic_string<char,std::char_traits<char>,std::allocator<char> > sDouble1="0.000000000001", std::basic_string<char,std::char_traits<char>,std::allocator<char> > sDouble2="1.E-12") Line 71 + 0x1a bytes C++

имеем

double1 1.0000000000000002e-012 double
double2 9.9999999999999998e-013 double


И то и другое — результат корректного преобразования строки в double. double — штука приближенная, поэтому рассчитывать на совершенно одинаковое преобразование из строки нельзя.

Надо просто ввести некоторое eps, и если величины отличаются не более чем на eps — считать их равными. Примерно так


int compareDouble( double double1, double double2 )
{
  if(fabs(double1-double2) < eps)
    return  0;
  else
    if (double2 > double1 )
    {
      return -1;
    }
    return 1;
}
With best regards
Pavel Dvorkin
Re[2]: конвертация строки в double
От: Erop Россия  
Дата: 27.05.10 11:11
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:


PD>Надо просто ввести некоторое eps, и если величины отличаются не более чем на eps — считать их равными. Примерно так

Только это епс должно быть относительной погрешностью, а не абсолютной
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: конвертация строки в double
От: Pavel Dvorkin Россия  
Дата: 27.05.10 11:24
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, Pavel Dvorkin, Вы писали:



PD>>Надо просто ввести некоторое eps, и если величины отличаются не более чем на eps — считать их равными. Примерно так

E>Только это епс должно быть относительной погрешностью, а не абсолютной

В теории — да. Практически — если известен диапазон допустимых значений и он узкий, то можно и абсолютную взять.
With best regards
Pavel Dvorkin
Re[3]: конвертация строки в double
От: Centaur Россия  
Дата: 27.05.10 11:28
Оценка:
Здравствуйте, Alezis, Вы писали:

S>>даже если два дабла бинарно идентичны, они не обязаны быть равны, как пример — NAN.

A>Мне важны чтобы разные представления числа из текстового файла давали на выходе алгоритма одни и те же результаты, а конкретно индекс в массиве.

WTF — вот здесь.

Использовать неточные значения как индексы в массиве — это Очень Плохая Идея. «Дайте мне строчку номер примерно полтора миллиона».

А для точных значений есть другие типы данных. Фиксированная точка, например.
Re[2]: конвертация строки в double
От: Alezis  
Дата: 27.05.10 11:33
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Здравствуйте, Alezis, Вы писали:


PD>Все правильно.


PD>Вот в этой функции при вызове из


PD>1.exe!compare_str_str__istrstream(std::basic_string<char,std::char_traits<char>,std::allocator<char> > sDouble1="0.000000000001", std::basic_string<char,std::char_traits<char>,std::allocator<char> > sDouble2="1.E-12") Line 71 + 0x1a bytes C++


PD>имеем


PD> double1 1.0000000000000002e-012 double

PD> double2 9.9999999999999998e-013 double


PD>И то и другое — результат корректного преобразования строки в double. double — штука приближенная, поэтому рассчитывать на совершенно одинаковое преобразование из строки нельзя.


PD>Надо просто ввести некоторое eps, и если величины отличаются не более чем на eps — считать их равными. Примерно так



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

PD>


Основная идея поста все таки была: непонятные разбежки в работе разных функций CRT и stl на моем компиляторе.
Получается что строки "0.000000000001" и "1.e-012" разные , но физически они представляют одно число. А на выходе я тоже могу получить разные результаты, причем для данного числа на atof, strtod все нормально.
Значит ли это что я всегда должен учитывать некий эпсилон, возможно найденный через fabs((double1-double2)/double1) причем независимо от диапазона рабочих чисел. Никто ведь не гарантирует что для какого то числа atof сконвертирует одно и тоже , верно ?
Re[3]: конвертация строки в double
От: Pavel Dvorkin Россия  
Дата: 27.05.10 11:43
Оценка:
Здравствуйте, Alezis, Вы писали:


PD>> double1 1.0000000000000002e-012 double

PD>> double2 9.9999999999999998e-013 double


A>Значит ли это что я всегда должен учитывать некий эпсилон, возможно найденный через fabs((double1-double2)/double1) причем независимо от диапазона рабочих чисел. Никто ведь не гарантирует что для какого то числа atof сконвертирует одно и тоже , верно ?


Никто ничего не гарантирует. Еще раз — оба вышеприведенных числа являются корректным результатом преобразования как из строки "0.000000000001", так и из строки "1E-12"
With best regards
Pavel Dvorkin
Re[4]: конвертация строки в double
От: Alezis  
Дата: 27.05.10 12:19
Оценка:
Здравствуйте, Centaur, Вы писали:

C>Здравствуйте, Alezis, Вы писали:


S>>>даже если два дабла бинарно идентичны, они не обязаны быть равны, как пример — NAN.

A>>Мне важны чтобы разные представления числа из текстового файла давали на выходе алгоритма одни и те же результаты, а конкретно индекс в массиве.

C>WTF — вот здесь.


C>Использовать неточные значения как индексы в массиве — это Очень Плохая Идея. «Дайте мне строчку номер примерно полтора миллиона».


C>А для точных значений есть другие типы данных. Фиксированная точка, например.

имелось ввиду что на основе некоего алгоритма я из вектора выбираю опредмеченное значение, понятное же дело что я не использую вещественные числа как индексы.
Re[5]: конвертация строки в double
От: Alezis  
Дата: 27.05.10 12:22
Оценка:
Здравствуйте, Alezis, Вы писали:

A>Здравствуйте, Centaur, Вы писали:


C>>Здравствуйте, Alezis, Вы писали:


S>>>>даже если два дабла бинарно идентичны, они не обязаны быть равны, как пример — NAN.

A>>>Мне важны чтобы разные представления числа из текстового файла давали на выходе алгоритма одни и те же результаты, а конкретно индекс в массиве.

C>>WTF — вот здесь.


C>>Использовать неточные значения как индексы в массиве — это Очень Плохая Идея. «Дайте мне строчку номер примерно полтора миллиона».


C>>А для точных значений есть другие типы данных. Фиксированная точка, например.

A>имелось ввиду что на основе некоего алгоритма я из вектора выбираю опредмеченное значение, понятное же дело что я не использую вещественные числа как индексы.
*определенное значение
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.