Лучше случайный алгоритм?

Я делаю игру в C++, и он связал заполняющиеся мозаики со случайными булевскими переменными (или да или не), является ли это да или не решено rand() % 1. Это не чувствует себя очень случайным.

Я использую srand с ctime при запуске, но кажется, что те же шаблоны подходят.

Есть ли какие-либо алгоритмы, которые создадут очень случайные числа? Или любые предложения о том, как я мог улучшиться rand()?

5
задан Bo Persson 13 November 2012 в 19:10
поделиться

13 ответов

Истинная случайность часто не кажется случайной. Ожидайте увидеть нечетные прогоны.

Но по крайней мере одна вещь, которую вы можете сделать, чтобы помочь, - это избегать использования только самого младшего бита. Процитируем числовые рецепты на C:

Если вы хотите сгенерировать случайное целое число от 1 до 10, вы всегда должны делать это, используя старшие биты, как в
j = 1 + (int) (10.0 * (rand() / (RAND_MAX + 1.0)));
, и никогда не используя ничего похожего на
j = 1 + (rand() % 10);
(который использует младшие биты).

Кроме того, вы можете рассмотреть возможность использования другого ГСЧ с лучшими свойствами. Алгоритм Xorshift - хорошая альтернатива. Он быстрый и компактный, занимает всего несколько строк на C и должен быть достаточно хорошим статистически практически для любой игры.

23
ответ дан 18 December 2019 в 05:18
поделиться

Также, если вы повторно засеваете слишком быстро, вы получите точно такой же номер. Лично я использую класс, который обновляет начальное число только при изменении времени.

-2
ответ дан 18 December 2019 в 05:18
поделиться

Для получения хороших результатов со случайными числами вам действительно нужен генератор, который объединяет результаты нескольких генераторов. Отказ от нижнего бита - довольно глупый ответ.

Умножение с переносом прост в реализации и дает хорошие результаты, а если у вас их несколько и объедините результаты, вы получите чрезвычайно хорошие результаты. Он также не требует много памяти и работает очень быстро.

-1
ответ дан 18 December 2019 в 05:18
поделиться

Люди говорят, что младшие биты не случайны. Так что попробуйте что-нибудь из середины. Это даст вам 28-й бит:

(rand() >> 13) % 2
0
ответ дан 18 December 2019 в 05:18
поделиться

Кнут предлагает генерацию случайных чисел методом вычитания. Это считается довольно случайным. Пример реализации на языке Scheme см. здесь

0
ответ дан 18 December 2019 в 05:18
поделиться

Младшие биты стандартных генераторов случайных чисел не очень случайны, это хорошо известная проблема.

Я бы посмотрел в библиотеку ускоренных случайных чисел .

1
ответ дан 18 December 2019 в 05:18
поделиться

Быстрая вещь, которая может сделать ваши числа более случайными, - это повторно заполнить генератор каждый раз, когда условие if (rand ()% 50 == 0) верно.

0
ответ дан 18 December 2019 в 05:18
поделиться

Я успешно использовал генератор случайных чисел Mersenne Twister в течение многих лет. Его исходный код доступен на математическом факультете Университета Хиросимы здесь . (Прямая ссылка, так что вам не нужно читать по-японски!)

В этом алгоритме замечательно то, что:

  1. Его «случайность» очень хороша
  2. Его вектор состояния - это вектор целых чисел без знака и index, поэтому очень легко сохранить его состояние, перезагрузить его и возобновить псевдослучайный процесс с того места, на котором он остановился.

Я бы рекомендовал взглянуть на него для вашей игры.

2
ответ дан 18 December 2019 в 05:18
поделиться

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

3
ответ дан 18 December 2019 в 05:18
поделиться

Самое простое, что вы можете сделать, кроме написания еще одного ГПСЧ или использования библиотеки, - это просто использовать все битов, которые дает вам один вызов rand () . Большинство генераторов случайных чисел можно разбить на поток битов, который имеет определенную случайность и статистические свойства. Отдельные биты, равномерно распределенные в этом потоке, не обязательно должны иметь одинаковые свойства. По сути, здесь вы отбрасываете от 14 до 31 бита псевдослучайности.

Вы можете просто кэшировать число, сгенерированное вызовом rand () , и использовать каждый его бит (в зависимости от количество битов rand () , конечно же, будет зависеть от RAND_MAX ). Поэтому, если ваш RAND_MAX равен 32768, вы можете последовательно использовать 15 младших битов этого числа. Особенно, если RAND_MAX настолько мал, что вы не имеете дело с младшими битами генератора, поэтому взятие битов с высокого уровня не принесет вам много. Например, Microsoft CRT генерирует случайные числа с помощью уравнения

x n + 1 = x n · 214013 + 2531011

, а затем смещается. младшие 16 бит этого результата и ограничивают его 15 битами. Так что никаких младших битов от генератора нет. Это в значительной степени справедливо для генераторов, где RAND_MAX достигает 2 31 , но иногда на это нельзя рассчитывать (так что, возможно, ограничьтесь 16 или 24 битами, взятыми из

Итак, как правило, просто кешируйте результат вызова rand () и последовательно используйте биты этого числа для своего приложения вместо rand ( )% 2 .

4
ответ дан 18 December 2019 в 05:18
поделиться

Идеальный способ случайного выбора Да или Нет переключает их. Вам может не понадобиться случайная функция.

1
ответ дан 18 December 2019 в 05:18
поделиться

Биты младшего разряда не очень случайны.
Используя% 2, вы проверяете только нижний бит случайного числа.

Предполагая, что вам не нужна случайность криптостойкости.
Тогда должно быть нормально следующее:

bool  tile = rand() > (RAND_MAX / 2);
8
ответ дан 18 December 2019 в 05:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: