Это то, что меня укусило.
Да, числа с плавающей точкой никогда не должны сравниваться для равенства из-за ошибки округления, и вы, вероятно, знали об этом.
Но в этом случае вы вычисляете t1+t2
, а затем вычисляете его снова. Несомненно,, который должен произвести идентичный результат?
Вот что, вероятно, происходит. Готов поспорить, что вы запускаете это на процессоре x86, правильно? FPU x86 использует 80 бит для своих внутренних регистров, но значения в памяти хранятся как 64-разрядные удваиваются.
Таким образом, t1+t2
сначала вычисляется с точностью до 80 бит, затем - предположим - сохраняется в памяти в sum_2
с 64-мя точками точности - и происходит некоторое округление. Для утверждения он загружается обратно в регистр с плавающей запятой, а t1+t2
вычисляется снова, снова с точностью до 80 бит. Итак, теперь вы сравниваете sum_2
, который был ранее округлен до 64-битного значения с плавающей запятой, с t1+t2
, который был рассчитан с более высокой точностью (80 бит) - и поэтому значения не совсем идентичны.
Редактировать Так почему же проходит первый тест? В этом случае компилятор, вероятно, оценивает 4.0+6.3
во время компиляции и сохраняет его как 64-битное количество - как для назначения, так и для assert.Таким образом сравниваются идентичные значения, и утверждение проходит.
Второй Редактировать Вот сборка код, сгенерированный для второй части кода (GCC, x86), с комментариями - в значительной степени следует вышеизложенному сценарию:
// t1 = 4.0
fldl LC3
fstpl -16(%ebp)
// t2 = 6.3
fldl LC4
fstpl -24(%ebp)
// sum_2 = t1+t2
fldl -16(%ebp)
faddl -24(%ebp)
fstpl -32(%ebp)
// Compute t1+t2 again
fldl -16(%ebp)
faddl -24(%ebp)
// Load sum_2 from memory and compare
fldl -32(%ebp)
fxch %st(1)
fucompp
Интересное примечание: Это был скомпилирован без оптимизации. Когда он скомпилирован с -O3
, компилятор оптимизирует все кода.
Вы можете посмотреть также: - [http://stackoverflow.com/questions/21265/comparing-ieee-floats-and-doubles-for-equality](http://stackoverflow.com/questions/21265/ сравнение-ieee-floats-and-doubles-for-equal) - [http://stackoverflow.com/questions/17333/most-effective-way-for-float-and-double-comparison](http://stackoverflow .com/questions/17333/most-effective-way-for-float-and-double-сравнение) - [http://stackoverflow.com/questions/713763/strange-results-with-floating-point-comparison] (http://stackoverflow.com/questions/713763/strange-results-with-floating-point-comparison) – pingw33n