C ++, Как оптимизируются арифметические операции с плавающей запятой?

Я наблюдал удивительное поведение при тестировании простых арифметических операций в предельных случаях на архитектуре x86:

const double max = 9.9e307; // Near std::numeric_limits::max()
const double init[] = { max, max, max };

const valarray myvalarray(init, 3);
const double mysum = myvalarray.sum();
cout << "Sum is " << mysum << endl;             // Sum is 1.#INF
const double myavg1 = mysum/myvalarray.size();
cout << "Average (1) is " << myavg1 << endl;    // Average (1) is 1.#INF
const double myavg2 = myvalarray.sum()/myvalarray.size();
cout << "Average (2) is " << myavg2 << endl;    // Average (2) is 9.9e+307

(Протестировано с помощью MSVC в режиме выпуска , а также gcc через Codepad. org. В режиме отладки MSVC среднее значение (2) устанавливается на #INF .)

Я ожидал, что среднее значение (2) будет равно среднему (1), но мне кажется, что встроенное разделение C ++ Оператор был оптимизирован компилятором и каким-то образом не позволил накоплению достичь #INF .
Вкратце: среднее значение больших чисел не дает #INF .

Я наблюдал такое же поведение с алгоритмом std на MSVC:

const double mysum = accumulate(init, init+3, 0.);
cout << "Sum is " << mysum << endl;             // Sum is 1.#INF
const double myavg1 = mysum/static_cast(3);
cout << "Average (1) is " << myavg1 << endl;    // Average (1) is 1.#INF
const double myavg2 = accumulate(init, init+3, 0.)/static_cast(3);
cout << "Average (2) is " << myavg2 << endl;    // Average (2) is 9.9e+307

(на этот раз, однако, gcc установил среднее значение (2) на #INF : http://codepad.org/C5CTEYHj .)

  1. Не могли бы вы объяснить, как был достигнут этот «эффект»?
  2. Это " особенность"? Или я могу считать это «неожиданным поведением», а не просто «неожиданным»?

Спасибо

10
задан Julien-L 19 April 2011 в 13:26
поделиться