Насколько хорошо java.util.Random? - программирование
Подтвердить что ты не робот

Насколько хорошо java.util.Random?

Два вопроса:

Я получу разные последовательности чисел для каждого семени, которое я в него вложил?

Есть ли какие-то "мертвые" семена? (Которые производят нули или повторяются очень быстро.)

Кстати, какие, если таковые имеются, другие PRNG следует использовать?

Решение. Поскольку я собираюсь использовать PRNG для создания игры, мне не нужна криптографическая защита. Я поеду с Mersenne Twister, как для скорости, так и для огромного периода.

4b9b3361

Ответ 1

В какой-то мере генераторы случайных чисел являются лошадьми для курсов. Класс Random реализует LCG с разумно выбранными параметрами. Но он по-прежнему обладает следующими особенностями:

Если это не имеет значения для вас, то Random имеет функцию погашения, предоставляемую как часть JDK. Это достаточно хорошо для таких вещей, как казуальные игры (но не те, где задействованы деньги). Слабые семена как таковые отсутствуют.

Другой альтернативой является генератор XORShift, который может быть реализован на Java следующим образом:

public long randomLong() {
  x ^= (x << 21);
  x ^= (x >>> 35);
  x ^= (x << 4);
  return x;
}

Для некоторых очень дешевых операций это имеет период 2 ^ 64-1 (ноль не разрешен) и достаточно прост, чтобы быть встроенным, когда вы генерируете значения повторно. Возможны различные значения сдвига: см. Статью Джорджа Марсалья о генераторах XORShift для получения более подробной информации. Вы можете рассматривать биты в числах, сгенерированных как одинаково случайные. Один из основных недостатков заключается в том, что иногда он попадает в "колею", где в количестве не так много бит, а затем требуется несколько поколений, чтобы выбраться из этой колеи.

Другие возможности:

  • объединять разные генераторы (например, подавать вывод из генератора XORShift в LCG, а затем добавлять результат к выходу генератора XORShift с разными параметрами): это обычно позволяет "сгладить" слабые стороны разных методов, и может дать более длительный период, если периоды комбинированных генераторов тщательно выбраны.
  • добавьте "задержку" (чтобы дать более длительный период): по существу, когда генератор обычно преобразует последнее число, сгенерированное, хранит "буфер истории" и преобразует, скажем, (n-1023) th.

Я бы сказал, избегайте генераторов, которые используют глупый объем памяти, чтобы дать вам период дольше, чем вам действительно нужен (у некоторых есть период, превышающий число атомов во Вселенной - вам это обычно не требуется), И обратите внимание, что "длительный период" не обязательно означает "генератор высокого качества" (хотя 2 ^ 48 все еще немного ниже!).

Ответ 2

Как сказал zvrba, JavaDoc объясняет нормальную реализацию. Страница страницы Wikipedia на генераторах псевдослучайных чисел содержит много информации и упоминает Mersenne twister, который не считается криптографически безопасным, но очень быстрым и имеет различные реализации в Java. (Последняя ссылка имеет две реализации - есть другие, я считаю.)

Если вам нужна криптографически безопасная генерация, прочитайте страницу Википедии - есть различные варианты.

Ответ 3

Поскольку RNG идут, реализация Sun определенно не state- of- theart, но достаточно хороша для большинства целей. Если вам нужны случайные числа для криптографических целей, java.security.SecureRandom, если вы просто хотите что-то быстрее и лучше, чем java.util.random, легко найти Java-реализации Mersenne Twister в сети.

Ответ 4

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

Ответ 5

См. ответ в моем сообщении в блоге:

http://code-o-matic.blogspot.com/2010/12/how-long-is-period-of-random-numbers.html

Случайный имеет максимальный период для своего состояния (длинный, т.е. 2 ^ 64 периода). Это может быть непосредственно обобщено на 2 ^ k - вложить столько бит состояния, сколько вы хотите, и вы получите максимальный период. 2Mersenne Twister на самом деле очень короткий период, сравнительно (см. Комментарии в упомянутом сообщении блога).

- К сожалению. Случайный ограничивает себя 48 бит, вместо того, чтобы использовать полные 64 бита длинного, соответственно, его период составляет 2 ^ 48, а не 2 ^ 64.

Ответ 6

Если качество RNG действительно имеет значение для вас, я бы рекомендовал использовать ваш собственный RNG. Возможно, java.util.Random просто замечательный, в этой версии, на вашей операционной системе и т.д. Это, вероятно, так. Но это может измениться. Раньше писатель библиотеки делал хуже в более поздней версии.

Очень просто написать свои собственные, и тогда вы точно знаете, что происходит. Это не изменится при обновлении и т.д. Здесь генератор