Сегодня утром у меня был небольшой момент WTF. Ths WTF можно резюмировать следующим образом:
float x = 0.2f;
float y = 0.1f;
float z = x + y;
assert(z == x + y); //This assert is triggered! (Atleast with visual studio 2008)
Похоже, что причина в том, что выражение x + y
продвигается в два раза и сравнивается с усеченной версией в z
. (Если я изменяю z
на double
, утверждение не запускается).
Я вижу, что по прецизионным соображениям было бы целесообразно выполнять всю арифметику с плавающей точкой в двойной точности, прежде чем преобразовать результат в единую точность. Я нашел следующий параграф в стандарте (который, я думаю, я уже знал, но не в этом контексте):
4.6.1.
"Значение типа float
может быть преобразовано в rvalue типа double
. Значение не изменяется"
Мой вопрос в том, что x + y
гарантируется, что он будет удвоен или находится на усмотрение компилятора?
ОБНОВЛЕНИЕ:. Поскольку многие люди утверждали, что нельзя использовать ==
для плавающей запятой, я просто хотел сказать, что в конкретном случае, с которым я работаю, точное сравнение оправданными.
Сравнение с плавающей точкой сложно, вот интересная ссылка по теме, о которой, как я думаю, не упоминалось.