Чет я прям зубы с пола от смеха собираю, читая эту тему. Ребятушко, ни один язык в мире не предоставляет гарантий точности вычислений с плавающей точкой.
Delphy - аналогично. То, что у них оно каким-то образом не валится - не повод этим свойством пользоваться. Ни разу.
Есть такое понятие в современных языках - undefined behavior. Неопределенное поведение, да. Это когда результат исполнения не зависит ни от стандарта, ни от документации, ни от компилятора.
Во всем мире более-менее грамотные программисты пользуют несколько иной способ проверки на равенство двух чисел с плавающей точкой: abs(x1 - x2) < eps
, где eps - какое-то маленькое число, обеспечивающее необходимую точность сравнения (например, 0.000001).
Объясняется подобное поведение тем, что в битовом представлении числа с плавающей точкой хранятся в виде, отличном от общепринятого. Вот тут можно глянуть. Некоторые из чисел в тех или иных формах попросту не представимы в предложенной модели. Когда встречается такое число, выбирается ближайшее к нему, которое представимо. Когда имеем сложное математическое выражение, вроде предложенного автором треда, скобки влияют на порядок вычислений, а следовательно - и на порядок появления погрешностей, поэтому на один и тот же пример можно получить разные ответы.
Эта форма представления общепринята, и используется во всех архитектурах современных процессоров, а значит, с ее ограничениями придется смириться.
Подчеркиваю - даже если какая-то среда (хоть Delphi, хоть Brainfuck) в каких-то случаях считает верно, на этот результат рассчитывать НЕЛЬЗЯ. За сравнение real на равенство вообще надо ошибку компиляции кидать, чтоб неповадно было. Сколько ж багов мир создал подобным образом…
В двоичной системе там хранятся на самом деле три числа в пределах одного 32-битного буфера памяти: знак, порядок, и мантисса. Простой перевод из одной системы в другую - несколько не то, что реально работает. Для 64 - суть та же, просто порядок с мантиссой больше места едят.