написать функцию c, которая генерирует одно случайное число, или пару случайных чисел, или триплет случайных чисел, заданных определенными диапазонами - PullRequest
2 голосов
/ 24 сентября 2010

Я должен генерировать случайные числа для 3 разных случаев. я. 1 кубик II. пара костей III. 3 кубика мои вопросы: 1. Пожалуйста, предложите мне хорошую логику для генерации случайных чисел для всех 3 случаев. 2. Изменится ли логика, когда я рассматриваю cses 2 кубиков, а не 1? 3. Насколько сильно влияет диапазон, в котором мы генерируем случайное число, на логику случайной функции?

Ответы [ 3 ]

5 голосов
/ 24 сентября 2010

Если диапазон достаточно мал, у вас не должно возникнуть проблем при использовании обычного метода по модулю

int GetRandomInt(int Min, int Max)
{
    return (rand()%(Max-Min+1))+Min;
}

(где Min a Max указывает закрытый интервал, [Min,Max])

и вызывать его один раз для каждого броска костейНе забудьте позвонить srand(time(NULL)) в начале приложения (в начале только , а не каждый раз, когда вы хотите получить случайное число), чтобы запустить генератор случайных чисел.

Если диапазон начинает увеличиваться, возможно, вам придется столкнуться с двумя проблемами:

Во-первых, диапазон rand() явно не равен [0, + ∞), вместо этого он равен [0, RAND_MAX], где RAND_MAX - это #define, гарантированное равное не менее 32767. Если ваш диапазон (Max-Min) превышает RAND_MAX, то с помощью этого метода вы получите несколько чисел с нулевой вероятностьюбыть возвращенным.

Это более тонко: предположим, что RAND_MAX больше вашего диапазона, но не , что больше, скажем, RAND_MAX==1.5*/(Max-Min).В этом случае распределение результатов не будет равномерным: rand() возвращает целое число в диапазоне [0, RAND_MAX] (и каждое целое число в этом диапазоне должно быть равновероятным), но вы берете остатокделение с (Max-Min).Это означает, что числа в первой половине требуемого диапазона имеют в два раза больше вероятности возврата, чем остальные: они могут на самом деле приходить из первых и третьей трети диапазона rand(), тогда какВторая половина необходимого диапазона может быть получена только из второй трети диапазона rand().

Что это значит для вас?

Вероятно, ничего.Если все, что вам нужно - это симулятор броска костей, вы можете без проблем использовать метод modulo, поскольку задействованный диапазон мал, а вторая проблема, несмотря на то, что все еще присутствует, почти не имеет значения:предположим, что ваш диапазон равен 3 и MAX_RAND 32767: от 0 до 32765, 0, 1 и 2 имеют одинаковую вероятность, но при увеличении до 32767 0 и 1 получают один потенциальный выход, что почти не имеет значения, поскольку они переходят от идеальногоВероятность 1/3 (10922/32766 = 0,333 ...) для каждого до 10922/32767 для 2 (~ 0,33332) и 10923/32767 (~ 0,33335) для 0 и 1 (при условии, что rand()обеспечивает идеальное распределение.

Во всяком случае, для преодоления таких проблем достаточно часто используемым методом является "растяжение" диапазона rand() в более широком диапазоне (или сжатие в меньшем диапазоне).) используя такой метод:

int GetRandomInt(int Min, int Max)
{
    return (int)(((double)rand())/MAX_RAND*(Max-Min))+Min;
}

на основе эквивалентности rand():MAX_RAND=X:(Max-Min).Необходимо преобразовать в double, иначе целочисленное деление между rand() и его максимальным значением всегда будет давать 0 (или 1 в редком случае rand()==MAX_RAND);это можно сделать в целочисленной арифметике, выполняя продукт первым, если MAX_RAND невелик и диапазон тоже не слишком широк, в противном случае существует высокий риск переполнения.

Я подозреваю, что если выходной диапазон больше, чем диапазон rand(), то «растяжение» и усечение значения fp (из-за преобразования в int) каким-то образом влияют на распределение, но тольколокально (например, в небольших диапазонах вы можете никогда не получить определенное число, но глобально распределение будет выглядеть нормально).

Обратите внимание, что этот метод помогает преодолеть диффузное ограничение генератора случайных чисел стандартной библиотеки C, т.е.низкая случайность младших битов возвращаемого значения, которые, кстати, используются при выполнении операции по модулю с небольшим выходным диапазоном.

Однако имейте в виду, что стандартная библиотека C для RNG является простой, которая стремится соответствовать «простым» статистическим правилам и поэтому легко предсказуема;его не следует использовать, когда требуются «серьезные» случайные числа (например, криптография).Для таких нужд существуют специальные библиотеки ГСЧ (например, часть ГСЧ Научной библиотеки GNU) или, если вам нужно действительно случайные вещи, есть несколько реальных службы случайных чисел (одна из самых известных - эта ), которые не используют математические псевдо-ГСЧ, но берут свои числа из реальных случайных источников (например, радиоактивного распада).

2 голосов
/ 24 сентября 2010

Да, как сказал DarkDust, это звучит как домашнее задание, поэтому, чтобы ответить на ваши вопросы с учетом этого, я бы сказал:

--> No, the logic doesnt not change, no matter how many dices you include.

--> Easiest way to do this would be, just make a function that give you ONE
    random function, and depending on how many dices you have, call it that
    many times. 

--> You can instead include for loop in the function and add the values into 
    array and return the array.

Таким образом, вы можете генерировать случайное число для 100 кубиковтоже.

1 голос
/ 24 сентября 2010

Поскольку это звучит как домашнее задание, я просто собираюсь дать подсказки, которые должны быть «достаточно хорошими» для вас (профессионал сделает это немного по-другому): используйте функцию random() и оператор % (по модулю),Модуло - это «напоминание» после деления.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...