C++,如何优化浮点算术运算?

Jul*_*n-L 10 c++ floating-point optimization

在x86架构上,在极限情况下测试简单的算术运算时,我观察到一种令人惊讶的行为:

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

const valarray<double> 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
Run Code Online (Sandbox Code Playgroud)

(在发布模式下使用MSVC进行测试,通过Codepad.org进行gcc测试.MSVC的调试模式将平均值(2)设置为#INF.)

我希望平均值(2)等于平均值​​(1),但在我看来,C++内置除法运算符已被编译器优化,并以某种方式阻止了累积达到#INF.
简而言之:大数字的平均值不会产生#INF.

我在MSVC上观察到与std算法相同的行为:

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

(但这次,gcc将平均值(2)设置为#INF:http://codepad.org/C5CTEYHj.)

  1. 有人会关心解释这种"效果"是如何实现的吗?
  2. 这是一个"功能"吗?或者我可以将此视为"意外行为"而不仅仅是"令人惊讶"?

谢谢

Chr*_*zig 4

只是猜测,但是: Average (2) 可能是直接在浮点寄存器中计算的,浮点寄存器的宽度为 80 位,并且比内存中双精度数的 64 位存储晚溢出。您应该检查代码的反汇编,看看情况是否确实如此。