Передача двойных типов в ceil приводит к различным значениям для разных уровней оптимизации в GCC - PullRequest
3 голосов
/ 24 июля 2010

Ниже значения переменных result1 и result2 сообщают о различных значениях в зависимости от того, Вы компилируете код с -g или с -O в GCC 4.2.1 и в GCC 3.2.0 (и я не пробовал более свежие версии GCC):

double double_identity(double in_double)
{
    return in_double;
}

...

double result1 = ceil(log(32.0) / log(2.0));
std::cout << __FILE__ << ":" << __LINE__ << ":" << "result1==" << result1 << std::endl;

double result2 = ceil(double_identity(log(32.0) / log(2.0)));
std::cout << __FILE__ << ":" << __LINE__ << ":" << "result2==" << result2 << std::endl;

result1 и result2 == 5 только при компиляции с использованием -g, но если вместо этого я скомпилирую с -O, я получу result1 == 6 и result2 == 5.

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

Выше было скомпилировано в C ++, но я предполагаю, что то же самое будет, если оно будет преобразовано в код ANSI-C с использованием printfs.

Вышеупомянутое несоответствие возникает в 32-битной Linux, но не в 64-битной Linux.

Спасибо BG

1 Ответ

6 голосов
/ 24 июля 2010

В x86 с включенной оптимизацией результаты подвыражений не обязательно сохраняются в 64-битной области памяти перед использованием в качестве части более крупного выражения.

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

64-разрядные процессоры Intel используют регистры SSE для математики с плавающей запятой, и эти регистры не имеют дополнительной точности.

Вы можете поиграть с g ++ flags , чтобы исправить это, если вам действительно интересно.

...