我正在从Objective C重写一个蒙特卡洛仿真,用于从VBA/Excel的DLL。计算中的“引擎”是创建一个介于0和10001之间的随机数,与5000-7000邻域中的变量进行比较。每次迭代使用4-800次,我使用100000次迭代。所以这是每次运行约50万次随机数。避免Monte Carlo模拟中的基本rand()偏差?
虽然在Objective C中测试显示没有偏见,但我对C代码有很大的问题。 Objective C是C的一个超集,所以95%的代码是复制粘贴并且很难搞砸。我昨天和今天整天都经历过很多次,而且我没有发现任何问题。
我留下了与使用srand()arc4random_uniform()和rand()之间的差异,尤其是因为偏向于更低的数字0到10000.我进行的测试与这种偏见一致对于低于大约5000的数字,0.5%到2%。其他任何解释是如果我的代码避免重复,我认为它没有做。
的代码是非常简单的(“spiller1evne”和“spiller2evne”是5500和6500之间的数字):
srand((unsigned)time(NULL));
for (j=0;j<antala;++j){
[..]
for (i=1;i<450;i++){
chance = (rand() % 10001);
[..]
if (grey==1) {
if (chance < spiller1evnea) vinder = 1;
else vinder = 2;
}
else{
if (chance < spiller2evnea) vinder = 2;
else vinder = 1;
}
现在我不需要真正的随机性,伪随机性是相当的精细。我只需要在累积的基础上大致均匀分布(如5555的可能性是5556的两倍),这并不重要,5500-5599的可能性比5600-5699的可能性高5%如果对0-4000有一个明确的0.5-2%的偏差超过6000-9999。
首先,rand()是否是我的问题,是否有一个简单的实现可以满足我的低需求?
编辑:如果我的怀疑是合理的,我能使用任何在此:
http://www.azillionmonkeys.com/qed/random.html
我将能够把刚才复制粘贴在作为替代(我写在C和使用Visual Studio,真正的新手)?:
#include <stdlib.h>
#define RS_SCALE (1.0/(1.0 + RAND_MAX))
double drand (void) {
double d;
do {
d = (((rand() * RS_SCALE) + rand()) * RS_SCALE + rand()) * RS_SCALE;
} while (d >= 1); /* Round off */
return d;
}
#define irand(x) ((unsigned int) ((x) * drand()))
EDIT2:那么显然上面的代码工作没有相同偏见,所以我会变成这样的人推荐谁拥有相同的“中间道路” - 就像我上面所描述的那样。它确实带来了罚款,因为它调用了rand()三次。所以我仍然在寻找更快的解决方案。
很简单的答案是,你不应该真的使用rand()进行严肃的蒙特卡洛模拟。 rand()是基于线性全等的,这很糟糕,你应该检查其他的RNG Mersenne Twister例如 – Jeanno 2015-03-31 14:06:39