напишите функцию c, которая генерирует одно случайное число, пару случайных чисел или тройку случайных чисел с заданными диапазонами

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


person wordwiz    schedule 24.09.2010    source источник


Ответы (3)


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

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

(где Min и 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().

Что это значит для тебя?

Наверное, ничего. Если все, что вы хотите сделать, это симулятор броска костей, вы можете без проблем использовать метод по модулю, поскольку вовлеченный диапазон невелик, а вторая проблема, несмотря на то, что все еще присутствует, она почти не имеет значения. : предположим, что ваш диапазон равен 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() обеспечивает < em>идеальное распределение).

Во всяком случае, для преодоления таких проблем довольно часто используется метод «растягивания» диапазона 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, то есть низкую случайность младших битов возвращаемого значения, которые, кстати, вы используете, когда выполняете операцию по модулю с небольшой выходной диапазон.

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

person Matteo Italia    schedule 24.09.2010
comment
Спасибо... именно то, что я искал. - person wordwiz; 24.09.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 игральных костей.

person iamserious    schedule 24.09.2010

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

person DarkDust    schedule 24.09.2010
comment
@Matteo Italia: в системах POSIX есть оба: int rand(void); и long random(void);, оба определены в stdlib.h. Хотя я понятия не имел о Windows. - person DarkDust; 24.09.2010
comment
Поскольку TS говорит о костях, я хотел бы отметить, что использование только по модулю даст загруженные кости из-за того, что MAX_RAND не кратен 6. Вы можете преодолеть это, используя по модулю 8 вместо по модулю 6 и отбрасывая числа › = 6 , Более подробную информацию можно найти в The Art of Programming by Knuth, глава о случайных числах (не помню точную ссылку). - person atzz; 24.09.2010
comment
Я проверил это, и это правда, что это было определено в stdlib.h, но в разделе Соответствие их справочных страниц указано, что rand() соответствует SVr4, 4.3BSD, C89, C99, POSIX.1-2001, а random() соответствует 4.3BSD, POSIX.1-2001, поэтому random кажется просто UNIX. вещи. В этом нет ничего плохого, но поскольку вопрос был о Си вообще, я подумал, что лучше использовать только стандартные функции Си. - person Matteo Italia; 24.09.2010