我正在從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