Почему установка переменной const (которая будет сохранена с тем же значением) приводит к другому результату после разделения? - PullRequest
0 голосов
/ 15 февраля 2019

Довольно basic код:

#include <iostream>

int main() {
    std::cout.precision(100);

    double a            = 9.79999999999063220457173883914947509765625;
    double b            = 0.057762265046662104872599030613855575211346149444580078125;
    const double bConst = 0.057762265046662104872599030613855575211346149444580078125;
    double c            = a * b;

    std::cout << "        a: " << a << std::endl;
    std::cout << "        b: " << b << std::endl;
    std::cout << "   bConst: " << bConst << std::endl;
    std::cout << "        c: " << c << std::endl << std::endl;  
    std::cout << "      c/b: " << c / b << std::endl;   
    std::cout << " c/bConst: " << c / bConst << std::endl;  
}

Какие выходы:

        a: 9.79999999999063220457173883914947509765625
        b: 0.057762265046662104872599030613855575211346149444580078125
   bConst: 0.057762265046662104872599030613855575211346149444580078125
        c: 0.5660701974567474703547986791818402707576751708984375

      c/b: 9.7999999999906304282148994388990104198455810546875
 c/bConst: 9.79999999999063220457173883914947509765625

Как видите, b и bConst, похоже, обрабатываютсяиспользуя одно и то же значение - т.е. он печатает для обоих одинаковое значение 0.057762265046662104872599030613855575211346149444580078125.Поэтому я думаю, что они «хранятся» одинаково.Единственная разница в том, что b не является const.

Затем я выполняю одну и ту же операцию c / b дважды: один раз, используя b, другой раз, используя bConst.

*.1020 * Как видите, это приводит к двум разным результатам.И это заставляет меня задуматься.

Можете ли вы технически объяснить, почему это происходит?

Ответы [ 2 ]

0 голосов
/ 15 февраля 2019

«Проблема» связана с переключателем -freciprocal-math (подразумевается -Ofast):

Позволяет использовать обратную величину значения вместо деления на значение, если это позволяетоптимизаций.Например, x / y можно заменить на x * (1/y), что полезно, если (1/y) подлежит общему исключению подвыражения.Обратите внимание, что это теряет точность и увеличивает число флопов, работающих со значением.

Компилятор может вычислить d = 1/bConst во время компиляции и изменить значение с:

c/bConst

на

c * d

но умножение и деление - это разные инструкции с разной производительностью и точностью.

См .: http://coliru.stacked -crooked.com / a / ba9770ec39ec5ac2

0 голосов
/ 15 февраля 2019

Вы используете -Ofast в своей ссылке, которая включает все -O3 оптимизации и включает обе -ffast-math, что, в свою очередь, включает -funsafe-math-optimizations.

Из того, что я мог найти, с включенной оптимизацией-funsafe-math-optimizations позволяет компилятору снизить точность некоторых вычислений.Это похоже на то, что происходит в случае c/bConst.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...