2012-03-24 4 views
4

Я опубликовал кучу генераторов случайных чисел с открытым исходным кодом on my site, включая генератор случайных чисел с нормально распределенным распределением. Чтобы генерировать случайное целое число в диапазоне 10-20, я бы написал что-то вроде new NormalRandomGenerator(10, 20).Next().Использование двойников для генерации случайного целого

Кто отправил этот комментарий:

Просто интересно, является ли это необходимо для реализации «Int Next()» в терминах «двойного NextDouble()», в качестве ИНТ двойных преобразований (и визы-Versa) может быть очень медленным на некоторых аппаратных средствах, в том числе на недавнем оборудовании ПК , хотя я не особенно современен на последних процессорах на данный момент.

Я считаю, что этот комментарий относится к тому факту, что, когда кто-то называет Next(20) на одном из моих классов, внутренне, что вызов переводится в нечто вроде (int)someMersenneTwister.NextDouble() * 20 (я не помню, если я округление).

Я реализовал его таким образом, потому что MT является быстрым и эффективным (хотя он имеет огромный случайный период). Из того, что я понимаю, это стандартный способ генерации случайных чисел - вызов Next(), который возвращает double в диапазоне [0 .. 1), а затем умножает и выводит на int.

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

Извините, если это звучит расплывчато. Я не уверен, есть ли здесь проблемы.

+2

Я даже не понимаю, как целые числа в ограниченном диапазоне могут иметь нормальное распределение/Гс. Это распределение возвращает непрерывные значения по всей вещественной оси. – CodesInChaos

+0

Может всегда маскировать биты для меньших чисел, которые, я думаю, будут быстрее. Тогда я ничего не получил. – SimpleVar

+0

Для * равномерных * целых чисел в заданном интервале проверки [мой вопрос] (http://stackoverflow.com/q/9499071/445517) и [моей случайной библиотеки] (https://github.com/MerkatorProject/Merkator.Tools /tree/master/Merkator.Tools/Random) – CodesInChaos

ответ

-1

Вы можете использовать «Random.Next» метод:

http://msdn.microsoft.com/en-us/library/system.random.next.aspx

Вы получите неотрицательное случайное число меньше указанного максимума, что ваше питание или дать диапазон чисел (мин и макс)

С уважением.

+0

Который возвращает довольно низкое качество. Вероятно, он использует алгоритм 'NextDouble * max'. По крайней мере, это объясняет его предвзятость. – CodesInChaos

3

Не ответ на ваш вопрос (потому что это не имеет смысла в его нынешней форме IMO). Но, просматривая ваш код, я вижу ряд ошибок и другие проблемы:

  1. Посев. Вы затрачиваете время, и это приводит к столкновениям с семенами при создании нескольких UniformRandomGenerator s в течение нескольких миллисекунд. Вы наследуете эту проблему от System.Random.
  2. MersenneTwister.NextDouble Низкое качество. double имеет примерно 53 цифры, вы заполняете 32. Почти так же плохо, как System.Random, который заполняет 31.
  3. MersenneTwister.Next(int maxValue) теперь растягивает этот плох двойной на желаемый интервал. Если интервал длинный, это может привести к сильным уклонениям. System.Random имеет очень похожую проблему.
  4. Next(int minValue, int maxValue) содержит переполнение Int при расчете maxValue-minValue
  5. Конструктор NormalRandomGenerator вычисляет среднее значение как this.Mean = ((max - min)/2) + min;. Это целочисленное деление и, следовательно, приводит к смещению, если max-min нечетно. Странный выбор, так как this.Mean - это двойной.
  6. Код для расчета нормально распределенных номеров выглядит странно, но я не могу вам помочь, так как я не знаю, что он должен делать.

Если вы хотите создать единообразные случайные числа, который является дубликат моего собственного вопроса: Generating uniform random integers with a certain maximum, которая сосредоточена на создание эффективны эти целых чисел без введения смещения. Я рекомендую объединить свой ответ с ответом LukeH.

+0

Отличный ответ, который объединяет все проблемы! –

+0

Отличный обзор кода, спасибо за это. Но, как вы сказали, не ответ на мой вопрос. – ashes999

+0

@ ashes999 Если вы укажете, что вы действительно хотите, мы можем ответить на вопрос. Но в настоящее время вы просите что-то невозможное/бессмысленное. – CodesInChaos

0

Генерирование случайных целых чисел путем масштабирования двойного диапазона [0..1) является хорошим, при условии, что сгенерированный двойник достаточно равномерно распределен. Тем не менее, большинство генераторов псевдослучайных чисел, включая Mersenne Twister, изначально генерируют (32-битные беззнаковые) целые числа, поэтому было бы неплохо, если бы нам не нужно было удвоить округление.

Если граница N является степенью 2, мы можем сначала сгенерировать 32-битное случайное целое число X и принять X mod N. Это гарантированно даст результат с четным распределением. Но если N не является степенью 2, взяв по модулю смещение в результирующем распределении (имеется больше 32-разрядных целых без знака, для которых X mod 7 равно 0, например 6.) Если N мало, то обнаружение таких смещение потребует огромного количества сгенерированных чисел, но теоретически распределение будет неправильным.

Для генерации целых чисел с действительно равномерным распределением в диапазоне [0..N) для N, который не является степенью двух, мы можем прибегнуть к алгоритму выборки: сначала вычислите M так, чтобы он был наименьшей степенью 2 больше чем N (для N = 13, M = 16 и т. д.). Затем сгенерируем 32-битное целое число X, вычислим Y = X mod M. Теперь, если Y < N, мы закончили, Y - наш номер. Если Y> = N, отбросьте его и сгенерируйте еще один, пока не появится Y < N. Если базовый prng хорош, ожидаемое число сгенерированных чисел никогда не превышает 2 (это зависит от N), и, хотя цикл не гарантированно заканчивается, он будет прерван с подавляющей вероятностью. В практическом приложении вам нужно поставить ограничительный счетчик в цикле и отложить на другой метод для защиты от генераторов дегазации.

Какой способ является самым быстрым? Скажет только профилирование. Это зависит от аппаратного обеспечения, языка и качества кода.

Более подробное обсуждение можно найти в TAOCP Кнута, часть 2.

Смежные вопросы