У меня есть следующий фрагмент кода:
#include <cstdio>
int main()
{
if ((1.0 + 0.1) != (1.0 + 0.1))
printf("not equal\n");
else
printf("equal\n");
return 0;
}
При компиляции с O3 с использованием gcc (4.4.4.5 и 4.6) и запуска изначально (ubuntu 10.10), он печатает ожидаемый результат "equal".
Однако тот же код, скомпилированный, как описано выше, и запускается на виртуальной машине (ubuntu 10.10, изображение виртуальной камеры), выводит "не равно" - это тот случай, когда установлены флаги O3 и O2, но не O1 и ниже. Когда компилируется с clang (O3 и O2) и запускается на виртуальной машине, я получаю правильный результат.
Я понимаю, что 1.1 не может быть правильно представлен с использованием double, и я читал "Что каждый компьютерный ученый должен знать о арифметике с плавающей точкой", поэтому, пожалуйста, не указывайте мне, это, кажется, какая-то оптимизация, GCC делает это как-то не работает на виртуальных машинах.
Любые идеи?
Примечание. В стандарте С++ говорится, что продвижение по типу в этих ситуациях зависит от реализации, может быть, GCC использует более точное внутреннее представление, которое при применении теста неравенства является истинным - из-за дополнительной точности?
UPDATE1: Следующая модификация вышеуказанного фрагмента кода теперь приводит к правильному результату. Кажется, в какой-то момент, по какой-либо причине, GCC отключает управляющее слово с плавающей запятой.
#include <cstdio>
void set_dpfpu() { unsigned int mode = 0x27F; asm ("fldcw %0" : : "m" (*&mode));
int main()
{
set_dpfpu();
if ((1.0 + 0.1) != (1.0 + 0.1))
printf("not equal\n");
else
printf("equal\n");
return 0;
}
UPDATE2:. Для тех, кто задает вопрос о характере кода выражения const, я изменил его следующим образом и все еще терпит неудачу при компиляции с помощью GCC. - но я полагаю, что оптимизатор может также преобразовывать следующее в выражение const.
#include <cstdio>
void set_dpfpu() { unsigned int mode = 0x27F; asm ("fldcw %0" : : "m" (*&mode));
int main()
{
//set_dpfpu(); uncomment to make it work.
double d1 = 1.0;
double d2 = 1.0;
if ((d1 + 0.1) != (d2 + 0.1))
printf("not equal\n");
else
printf("equal\n");
return 0;
}
UPDATE3 Разрешение: Обновление виртуального бокса до версии 4.1.8r75467 разрешило проблему. Однако их остается одной проблемой, то есть: почему работала работа клана.