Случайный едва случайно вообще?

Я сделал это для тестирования случайности randint:

>>> from random import randint
>>>
>>> uniques = []
>>> for i in range(4500):  # You can see I was optimistic.
...     x = randint(500, 5000)
...     if x in uniques:
...         raise Exception('We duped %d at iteration number %d' % (x, i))
...     uniques.append(x)
...
Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
Exception: We duped 887 at iteration number 7

Я попробовал приблизительно в 10 раз больше и лучший результат, который я получил, было 121 повторение перед повторителем. Действительно ли это - лучший вид результата, который можно получить от стандартной библиотеки?

74
задан Andriy M 8 June 2015 в 12:12
поделиться

10 ответов

Используйте класс почтовой рассылки PHP, такой как PHPmailer или SwingMailer , вы можете отправлять почту непосредственно через SMTP, который путь, что будет намного быстрее. И да, отправка большого количества электронных писем лучше всего выполнять через cron, так что вы отправляете X электронных писем каждую минуту. Путь можно избежать перегрузки сервера. Если вы не можете создать cron задания на вашем сервере я предлагаю вам переключить ваш хостинг провайдер, в противном случае веб-сайт, который вы связали является вашей единственной жизнеспособной альтернативой (но вы зависите от какой-то третьей стороны таким образом, что не очень круто)

-121--4028742-

С точки зрения покупателя, я не хочу, чтобы мое имя пользователя было DWong1145.

-121--3787347-

Парадокс дня рождения или почему PRNG производят дубликаты чаще, чем вы думаете.


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

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

Быстрый праймер на генераторах псевдослучайных чисел (PRNG)

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

Некоторые алгоритмы, такие как линейный конгруэнтный PRNG ( A '= AX' M ) , гарантируют уникальность для всего периода. В LCG генерируемое значение содержит все состояние аккумулятора и не удерживается дополнительное состояние. Генератор детерминирован и не может повторять число в пределах периода - любое заданное значение накопителя может подразумевать только одно возможное последовательное значение. Поэтому каждое значение может возникать только один раз в пределах периода генератора. Однако период такого PRNG относительно мал - около 2 ^ 30 для типичных реализаций алгоритма LCG - и не может быть больше, чем количество отдельных значений.

Не все алгоритмы PRNG имеют общую эту характеристику; некоторые могут повторять заданное значение в пределах периода. В проблеме ОП,алгоритм Мерсенна Твистера (используемый в случайном модуле Пайтона) имеет очень длинный период - намного больше 2 ^ 32. В отличие от линейного конгруэнтного PRNG, результат не является чисто функцией предыдущего выходного значения, поскольку аккумулятор содержит дополнительное состояние. При 32-разрядном целочисленном выходе и периоде ~ 2 ^ 19937 он не может обеспечить такую гарантию.

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

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

  • Хорошие геометрические свойства означают, что наборы N чисел не лежат на гиперплоскости в N-мерном пространстве. Плохие геометрические свойства могут создавать ложные корреляции в расчетной модели и искажать результаты.

  • Длительный период означает, что можно сгенерировать большое количество чисел до начала последовательности. Если модель нужна в большом количестве повторений или должна управляться от нескольких семян тогда 2^30 или таким образом, дискретные числа, доступные от типичного внедрения LCG, могут не быть достаточными. Алгоритм MT19337 имеет очень длинный период - 2 ^ 19337-1, или около 10 ^ 5821. Для сравнения, общее количество атомов во Вселенной оценивается примерно в 10 ^ 80.

32-битное целое число, полученное посредством MT19337 PRNG, не может представлять достаточно дискретных значений, чтобы избежать повторения в течение такого большого периода. В этом случае дублирование значений, вероятно, произойдет и неизбежно при достаточно большой выборке.

Парадокс дня рождения в двух словах

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

This graph shows the probability of a shared birthday as the number of people in the room increases.  For 23 people the probability of two sharing a birthday is just over 50%.

Вероятность совпадения между любыми двумя лицами намного выше, чем вероятность совпадения с конкретным лицом, поскольку совпадение не должно приходиться на конкретную дату. Скорее, вы должны найти только двух людей, которые разделяют один и тот же день рождения. Из этого графика (который можно найти на странице Википедии по теме) мы видим, что нам нужно только 23 человека в комнате, чтобы 50% шанс найти два, что соответствует таким образом.

Из записи Википедии по теме мы можем получить приятное резюме. В проблеме ОП у нас 4500 возможных «дней рождения», а не 365. Для данного числа сгенерированных случайных значений (приравнивающихся к «людям») мы хотим знать вероятность любого двух идентичных значений, появляющихся в последовательности.

Вычисление вероятного влияния парадокса дня рождения на проблему ОП

Для последовательности из 100 чисел мы имеем (100 * 99) / 2 = 4950 пар (см. Понимание проблемы ), которая потенциально может совпадать (т.е. первая может совпадать со второй, третьей и т.д., вторая может совпадать с третьей, четвертой и т.д.)поэтому количество комбинаций , которые потенциально могут совпадать, больше, чем просто 100.

Из вычисления вероятности получается выражение 1 - (4500! / (4500**100 * (4500 - 100)!) . Следующий ниже фрагмент кода Python делает наивную оценку вероятности совпадения пары.

# === birthday.py ===========================================
#
from math import log10, factorial

PV=4500          # Number of possible values
SS=100           # Sample size

# These intermediate results are exceedingly large numbers;
# Python automatically starts using bignums behind the scenes.
#
numerator = factorial (PV)          
denominator = (PV ** SS) * factorial (PV - SS)

# Now we need to get from bignums to floats without intermediate
# values too large to cast into a double.  Taking the logs and 
# subtracting them is equivalent to division.
#  
log_prob_no_pair = log10 (numerator) - log10 (denominator)

# We've just calculated the log of the probability that *NO*
# two matching pairs occur in the sample.  The probability
# of at least one collision is 1.0 - the probability that no 
# matching pairs exist.
#
print 1.0 - (10 ** log_prob_no_pair)

Это дает разумный результат просмотра p = 0,669 для совпадения, происходящего в пределах 100 чисел, отобранных из совокупности из 4500 возможных значений. (Возможно, кто-то может проверить это и опубликовать комментарий, если это неправильно). Из этого видно, что длины пробегов между совпадающими числами, наблюдаемыми ОП, кажутся вполне разумными.

Сноска: использование тасования для получения уникальной последовательности псевдослучайных чисел

См. этот ответ ниже от С. Марка для получения гарантированного уникального набора случайных чисел. Техника, к которой относится плакат, берет массив чисел (которые вы поставляете, так что вы можете сделать их уникальными) и перетасовывает их в случайный порядок. Рисование чисел в последовательности из тасованного массива даст вам последовательность псевдослучайных чисел, которые гарантированно не повторяются.

Сноска: криптографически защищенные PRNG

Алгоритм MT не криптографически защищен , так как относительно легко вывести внутреннее состояние генератора, наблюдая последовательность чисел. Другие алгоритмы, такие как Blum Blum Shub , используются для криптографических приложений, но могут быть непригодны для моделирования или общих приложений случайных чисел. Криптографически защищенные PRNG могут быть дорогими (возможно, требуют расчетов bignum) или не иметь хороших геометрических свойств. В случае алгоритма этого типа основное требование состоит в том, что он должен быть вычислительно невозможен для вывода внутреннего состояния генератора путем наблюдения последовательности значений.

279
ответ дан 24 November 2019 в 11:44
поделиться

Случайная реализация Python на самом деле довольно современное состояние искусства:

5
ответ дан 24 November 2019 в 11:44
поделиться

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

Если вы когда-нибудь свернули кости, вы обязательно часто получаете 3 шестерся в ряд ...

15
ответ дан 24 November 2019 в 11:44
поделиться

Это не повторитель. Репретеритор - это когда вы повторите одну и ту же последовательность . Не только один номер.

4
ответ дан 24 November 2019 в 11:44
поделиться

Перед тем, как обвинять Пайтона, тебе действительно стоит почистить теорию вероятности и статистики. Начните с чтения о парадоксе дня рождения

Кстати, в модуле random на Python используется Mersenne twister PRNG, который считается очень хорошим, имеет огромный период и был тщательно протестирован. Так что будьте уверены, что вы в хороших руках.

44
ответ дан 24 November 2019 в 11:44
поделиться

Вы генерируете 4500 случайные числа из диапазона 500 <= x <= 5000. Затем вы проверяете для каждого числа, было ли оно сгенерировано ранее. Проблема дня рождения говорит нам о том, какова вероятность того, что два из этих чисел совпадут с заданным n числом, которое пытается выйти из диапазона d.

Также можно инвертировать формулу, чтобы вычислить, сколько чисел нужно сгенерировать до тех пор, пока вероятность генерации дубликата не превысит 50% . В этом случае у Вас есть >50% шанс найти дубликат числа после 79 итераций.

4
ответ дан 24 November 2019 в 11:44
поделиться

Если вам не нужен репетативный, создайте последовательный массив и используйте random.shuffle

40
ответ дан 24 November 2019 в 11:44
поделиться
  • некоторые варианты gvim не могут обработать некоторые из моих горячих клавиш

  • некоторые создают отдельное окно, когда я пытаюсь для компиляции программы

  • иногда они просто не могут использовать шрифты как фиксированное или правильное окончание (подумайте о «terminus bold» - некоторые gvim вариации просто растянуть «terminus normal» вместо «terminus normal» визуализация с помощью отдельного шрифта)

  • cli обычно работает быстрее, чем gui, особенно если работает в реальном textmode console (невозможно на mac хотя)

  • почти нет преимуществ в использовании Версия GUI, и я бы потерял способность запустить на экране ssh для приостановки обработка с помощью ctrl + z и многие другие.

-121--2360716-

Можно использовать элемент управления WebBrowser , который можно в определенной степени автоматизировать.

-121--2587906-

Для кого-либо еще с этой проблемой я использовал uuid.uuid4 () и это работает как шарм.

0
ответ дан 24 November 2019 в 11:44
поделиться

Вы определили случайное пространство 4501 значений (500-5000), и вы итерация 4500 раз. Вы в основном гарантированно получите столкновение в тесте, который вы написали.

Чтобы подумать об этом другим способом:

  • Когда массив результатов пуст P (DUPE) = 0
  • 1 значение в массиве P (DUPE) = 1/4500
  • 2 значения в массиве P (DUPE ) = 2/4500
  • и т. Д.

Итак, к тому времени, когда вы дойдете до 45/4500, что вставка имеет 1% шанс быть дубликатом, и эта вероятность продолжает увеличиваться с каждой последующей вставкой.

Чтобы создать тест, который действительно тестирует способности случайной функции, повысить вселенную возможные случайные значения (например,: 500-500000), вы можете, или не можете получить дуп. Но вы получите гораздо больше итераций в среднем.

1
ответ дан 24 November 2019 в 11:44
поделиться

В качестве ответа на ответ Нимбуза:

http://xkcd.com/ 221 /

alt text

38
ответ дан 24 November 2019 в 11:44
поделиться
Другие вопросы по тегам:

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