В этом вопросе StackOverflow:
Создание случайного целого из диапазона
принятый ответ предлагает следующую формулу для генерации случайного целого числа между заданными min
и max
, причем min
и max
включены в диапазон:
output = min + (rand() % (int)(max - min + 1))
Но в нем также говорится, что
Это все еще немного смещено к более низким номерам... Это также возможно продлить его так, чтобы он удалял смещение.
Но это не объясняет, почему оно предвзято относится к более низким номерам или как устранить смещение. Итак, возникает вопрос: является ли это наиболее оптимальным подходом к генерации случайного целого в пределах (подписанного) диапазона, не полагаясь ни на какую фантазию, просто на функцию rand()
, а в случае, если она является оптимальной, как удалить смещение
EDIT:
Я только что протестировал алгоритм while
-loop, предложенный @Joey против экстраполяции с плавающей запятой:
static const double s_invRandMax = 1.0/((double)RAND_MAX + 1.0);
return min + (int)(((double)(max + 1 - min))*rand()*s_invRandMax);
чтобы увидеть, как равномерно "шары" "падают" и распределяются между несколькими "ведрами", один тест для экстраполяции с плавающей запятой и другой для алгоритма while
-loop. Но результаты оказались разными в зависимости от количества "шаров" (и "ведер" ), поэтому я не мог легко выбрать победителя. Рабочий код можно найти на этой странице Ideone. Например, с 10 ведрами и 100 шарами максимальное отклонение от идеальной вероятности среди ведер меньше для экстраполяции с плавающей запятой, чем для алгоритма while
-loop (0,04 и 0,05 соответственно), но с 1000 шарами максимальное отклонение алгоритм while
-loop меньше (0,024 и 0,011), а с 10000 шарами экстраполяция с плавающей запятой снова улучшается (0,0034 и 0,0053) и т.д. без значительной согласованности. Думая о возможности того, что ни один из алгоритмов не будет последовательно создавать однородное распределение лучше, чем у другого алгоритма, заставляет меня склоняться к экстраполяции с плавающей запятой, поскольку она работает быстрее, чем алгоритм while
-loop. Так хорошо выбрать алгоритм экстраполяции с плавающей запятой или мои тесты/выводы не совсем корректны?