【发布时间】:2011-04-19 22:55:05
【问题描述】:
在 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
(在 release 模式下使用 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
(不过,这次 gcc 将平均值 (2) 设置为 #INF: http://codepad.org/C5CTEYHj。)
- 有人愿意解释一下这种“效果”是如何实现的吗?
- 这是一个“功能”吗?或者我可以认为这是一种“意外行为”而不是简单的“令人惊讶”吗?
谢谢
【问题讨论】:
-
无法访问codepad.org。
init数组的内容是什么?{9.9e+307,9.9e+307,9.9e+307}? -
@KennyTM:是的,我忘记了问题中的代码(现已更新)。谢谢。
标签: c++ optimization floating-point