我最近偶然发现了一个 C++ 错误/功能,我无法完全理解,并希望这里有更好的 C++ 知识的人可以为我指明正确的方向。
下面你会发现我尝试使用蒙特卡洛积分找出高斯曲线下的面积。食谱是:
- 生成大量正态分布的随机变量(均值为 0,标准差为 1)。
- 平方这些数字。
- 取所有正方形的平均值。平均值将是曲线下面积的非常接近的估计值(在高斯的情况下,它是 1.0)。
下面的代码由两个简单的函数组成:rand_uni
,它返回一个随机变量,均匀分布在 0 和 1 之间,以及rand_norm
,它是正态分布随机变量的一个(相当差,但“足够好”)近似值。
main
循环运行十亿次,rand_norm
每次调用,将其平方pow
并添加到累积变量中。在此循环之后,累积的结果仅除以运行次数并打印到终端作为Result=<SOME NUMBER>
.
问题在于下面代码的非常古怪的行为:当每个生成的随机变量被打印到cout
(是的,十亿次)时,无论使用什么编译器,最终结果都是正确的(1.0015,非常接近,我想)。如果我不在每次循环迭代中打印随机变量,我会得到inf
448314gcc
和clang
.
坦率地说,这只是令人难以置信,因为这是我第一次(-ish)遇到 C++,我真的不知道问题可能是什么:它与pow
? cout
行为怪异吗?
任何提示将不胜感激!
来源
// Monte Carlo integration of the Gaussian curve
#include <iostream>
#include <cstdlib>
#include <cmath>
using namespace std;
enum {
no_of_runs = 1000000
};
// uniform random variable
double rand_uni() {
return ((double) rand() / (RAND_MAX));
};
// approximation of a normaly distributed random variable
double rand_norm() {
double result;
for(int i=12; i > 0; --i) {
result += rand_uni();
}
return result - 6;
};
int main(const int argc,
const char** argv) {
double result = 0;
double x;
for (long i=no_of_runs; i > 0; --i) {
x = pow(rand_norm(), 2);
#ifdef DO_THE_WEIRD_THING
cout << x << endl; // MAGIC?!
#endif
result += x;
}
// Prints the end result
cout << "Result="
<< result / no_of_runs
<< endl << endl;
}
生成文件
CLANG=clang++
GCC=g++
OUT=normal_mc
default: *.cpp
$(CLANG) -o $(OUT).clang.a *.cpp
$(CLANG) -o $(OUT).clang.b -DDO_THE_WEIRD_THING *.cpp
$(GCC) -o $(OUT).gcc.a *.cpp
$(GCC) -o $(OUT).gcc.b -DDO_THE_WEIRD_THING *.cpp