Почему эта функция stl возвращает это двойное значение?

Следующее утверждение не работает в RAD Studio 2010 (и, кстати, будет выполнено в Visual Studio 2010):

double              d1 = 0.0104;
double              d2 = 0.0;
std::istringstream  ss("0.0104");
ss >> d2;
assert(d1 == d2);

Это меня немного удивило. Я проследил до оператора извлечения, чтобы увидеть, что происходит, дошел до dinkumware/xlocnum и не смог проследить дальше.

Может ли кто-нибудь сказать мне, почему __Stodx(... "0.0104") возвращает значение, которое незначительно отличается от двойного инициализированного значения 0.0104?

(Я знаю, что некоторые значения не могут быть точно представлены в двоичном формате. Я хочу знать, почему результирующие двойники содержат разные значения, чтобы я мог это понять.)

Спасибо!


person Matthew Lowe    schedule 10.11.2011    source источник
comment
Не могли бы вы прочитать ссылку, указанную в ответе?   -  person Sergei Nikulov    schedule 10.11.2011
comment
Да. Я знаю об этой проблеме (я знаю, что некоторые значения не могут быть точно представлены в двоичном виде...), но я хочу знать, что /точно/ происходит в этом случае с этим компилятором. Я хочу знать, что происходит в упомянутом stod(), что отличается от того, когда инициализируется двойной.   -  person Matthew Lowe    schedule 10.11.2011
comment
разница только в вычислительном характере strtod - например, koders.com/c/ .   -  person Sergei Nikulov    schedule 10.11.2011
comment
Я тоже этого ожидаю, Сергей. Я надеюсь, что кто-то с глубоким знанием компилятора/библиотек Embarcadero сможет рассказать мне больше.   -  person Matthew Lowe    schedule 11.11.2011


Ответы (2)


Вот ответ на этот вопрос.

[29.17] Почему не работает сравнение с плавающей запятой?

Потому что арифметика с плавающей запятой отличается от арифметики вещественных чисел.

Итог: никогда не используйте == для сравнения двух чисел с плавающей запятой.

Здесь ответ на вопрос "почему результирующие двойники содержат разные значения"

  1. d1 - точное постоянное представление, предоставленное компилятором
  2. d2 вычисляется во время преобразования (см. пример strtod), поэтому возможны некоторые ошибки округления при вычислении с плавающей запятой, как описано здесь и здесь
person Sergei Nikulov    schedule 10.11.2011
comment
Извините, но я не могу принять этот ответ. Это просто неправильно. Проблема не в том, что strtod может иметь ошибки округления, а d1 не является точным представлением константы. Это представление обеспечивается любым методом, используемым компилятором для преобразования строк в двойные числа, который явно отличается от метода, используемого dinkumware. Я думаю, что правильный ответ на мой вопрос выглядит примерно так: компилятор и библиотека используют разные методы для преобразования строк в удвоения, и без доступа к исходному коду компилятора никто не сможет сказать вам, чем эти методы отличаются. - person Matthew Lowe; 13.02.2012

Дорогой я! Компилятор и библиотека используют разные методы для преобразования строк в двойные, и без доступа к исходному коду компилятора никто не сможет сказать вам, чем эти методы отличаются.

Извини меня

person Matthew Lowe    schedule 15.02.2012