Я переписываю симуляцию Монте-Карло на C из Objective C для использования в dll из VBA/Excel. «Двигателем» расчета является создание случайного числа от 0 до 10001, которое сравнивается с переменной в районе 5000-7000. Это используется 4-800 раз за итерацию, и я использую 100000 итераций. Таким образом, получается около 50 000 000 генераций случайных чисел за прогон.
В то время как в Objective C тесты не показали предвзятости, у меня огромные проблемы с кодом C. Objective C — это надмножество C, поэтому 95% кода было скопировано, и его трудно испортить. Я прошел остальные много раз весь день вчера и сегодня, и я не нашел никаких проблем.
У меня осталась разница между arc4random_uniform() и rand() с использованием srand(), особенно из-за смещения в сторону меньших чисел от 0 до 10000. Проведенный мной тест согласуется с таким смещением от 0,5 до 2% к числам ниже примерно 5000. Любое другое объяснение состоит в том, что мой код избегал повторений, чего, я думаю, не происходит.
код очень прост ("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 на 5% более вероятно, чем 5600-5699 и если есть явное смещение 0,5-2% в сторону 0-4000, чем 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() три раза. Поэтому я все еще ищу более быстрое решение.