我的同事和我正在用C ++一起开展一个蒙特卡洛项目。她使用Visual Studio,我使用Xcode,我们通过git共享代码。 由于需要随机数生成的给定方法,我们正在计算美国期权价格。我们意识到我们得到了某个参数K的错误结果(参数越高,答案就越错),我的同事发现将Mersenne Twister的随机源更改为rand()(尽管生成器很差)使得结果良好对于整个K范围。
但是当我在我的代码版本上更改源代码时,它什么也没做。
对我来说更令人费解的是,我创建了一个新的Xcode项目,在其中复制了她的整个源代码并且它仍然给我错误的结果(当她得到好的时候)。所以它不能源于代码本身。 我清理了项目,重新启动了Xcode,甚至重新启动了我的计算机(...),但没有任何变化:我们的项目行为一致但不同,后面的代码相同。 (编辑:通过不同但一致的方式,我并不意味着我们没有相同的数字序列。我的意思是她的蒙特卡罗估计会收敛到4,然后收敛到3。)
您是否了解这种双重行为的原因是什么?
这是随机生成代码:
double loiuniforme() //uniform law
{
return (double)((float)rand() / (float)RAND_MAX);
}
vector<double> loinormale() //normal law
{
vector<double> loinormales(2, 0.);
double u1 = loiuniforme();
double v1 = loiuniforme();
loinormales[0] = sqrt(-2 * log(u1))*cos(2 * M_PI*v1);
loinormales[1] = sqrt(-2 * log(u1))*sin(2 * M_PI*v1);
return(loinormales);
}
编辑:之前使用的MT RNG是:
double loiuniforme()
{
mt19937::result_type seed = clock();
auto real_rand = std::bind(std::uniform_real_distribution<double>(0,1), mt19937(seed));
return real_rand();
}
答案 0 :(得分:2)
C ++标准未指定rand()
使用的算法。编写编译器的人可以自由地使用他们想要的任何实现,并且无法保证它在两个不同的编译器,两个不同的体系结构甚至同一个编译器的两个不同版本上的行为相同。
答案 1 :(得分:2)
您应该只创建一个生成器并将其用于每个数字。
mt19937::result_type seed = clock();
和
mt19937(seed)
每次调用该函数时,都会创建一个带有新种子的新生成器 这导致随机性变得全部扭曲。
您可以在函数中使用静态变量,因为这些是在第一次调用时初始化的:
double loiuniforme()
{
static std::mt19937 generator(clock());
static std::uniform_real_distribution<double> distribution(0, 1);
return distribution(generator);
}
(当您与同事比较结果时,请使用相同的硬编码种子来验证您获得相同的结果。)
答案 2 :(得分:0)
您需要在两台计算机上使用相同的号码播种rand
函数。即便如此,我也不确定计算机和操作系统中的底层代码是否会返回相同的值。
更重要的是,如果您想要相同的结果,请不要使用随机函数。