Событие с заданной вероятностью
05.05.2011 технологии
С наскока не придумал красивого лаконичного решения, решил погуглить и сразу же нашёл клёвый вариант. Что странно, с маулнетовского форума! Отсюда. Вот такое решение предложили, простейшее условие в PHP: if (rand(1, 100) <= $chance)...
Мне нравится. Естественно, этот простейший алгоритм подойдёт вообще для любого языка с генератором [псевдо]случайных чисел. Жаль немного, что не сам дошёл до такой простой реализации. Туплю, а под утро — особенно.
Комментарии
Комментирование этой статьи закрыто.
Может спать пораньше ложиться?)
Да что-то режима нет снова никакого. Спать ложусь — не могу успокоиться, мысли всякие. Встаю и снова за комп. Есть у меня проблемы с расслаблением.
Ох, ох… Ну вот я на php не пишу. Вот у меня пятый час ночи. И я вижу твой пост в rss. И даже в пятом часу ночи я с первого взгляда задницей чую что это не будет работать нормально.
И первый пяток ссылок в гугле это подтверждает
tjl.co/blog/code/fol…
Не говоря уже о быстродейсвии
Впрочем, как и мою все более укрепляющуюся уверенность в том что если ты пишешь на php, то будь готов что нужно смотреть в исходниках как реализованы те или иные функции.
Ну это ж приблизительно, на то они и вероятности. Что значит «нормально» в твоём понимании? Я потому «псевдо» и написал, что вроде как действительно настоящего случайного генератора чисел вообще не существует. Для большинства же задач решение с rand(1,100), по-моему, вполне приличное.
Но ссылка прикольная, спасибо. Клёво чувак придумал, хорошо на картинках видна упорядоченность «случайностей».
Чисто интересно, а как ты собирался делать это по своему, до гугления? :)
Да какие-то замудрёные конструкции, сейчас не вспомню даже точно. В общем, не то, чем стоило бы гордиться и что имело бы смысл показывать :)
Но ссылка прикольная, спасибо. Клёво чувак придумал, хорошо на картинках видна упорядоченность «случайностей».
Вспомнил, что была такая-же проблема на БК-0010. point(rnd(), rnd()), rnd() выдавала ровные диагональные линии. Решалось очень просто – один дополнительный rnd в цикле. Тут так не прокатит, судя по опыту.
P.S.: сам всегда mt_rand использую.
Лучше использовать srand. И не забывай инициировать генератор случайных чисел перед использованием srand, иначе результат может быть странным
@kp: чем лучше? И кстати, «Since PHP 4.2.0, the seed becomes optional and defaults to a random value if omitted.»
kp, бред. srand как раз и изменяет начальное число генератора псевдослучайных чисел. С версии 4.2 это делается автоматически
лучше использовать /dev/urandom
Меня постоянно смущает вот эта «псевдо». Народ, уже много лет рандом не надо инициировать и посеивать, он нормально работает.
Если вы до свих пор считаете, что это «псевдо»-случайность – попробуйте назвать следующее число в ряду 17, 901, 309 (rand(1, 1000), само собой).
Если вам мешает паранойя – придумайте невхерственное шифрование, например, возведение в «псевдо«случайную степень, деление на е в «псевдо«случайной степени, взять «псевдо«случайные по порядку цифры, найти факториал и извлечь квадратный корень из этого, напоследок забрав последние N цифр после точки.
Ёлки-палки, если до сих пор всё псевдослучайно – дайте мне расшифровку порядка расклада карт в онлайн-казино. Это же несложно?
Ах да, чуть не забыл. По ссылке выше не забываем посмотреть на дату публикации.
Несколько нюансов. Во первых различные телодвижения типа взведения в степень и т.п. только ухудшают качестве генератора. Это раз. Во во вторых, зная чем проиницилизирован rand-ом, я могу точно сказать следующе число. А то есть любители брать системное время, делать srand от него и потом удивлятся почему можно предсказать.
А про онлайн казино – нормальные используют аппаратный генератор не просто так.
В предыдущем сообщении ошибся, инициировать генератор через mt_srand и потом пользоваться через mt_rand. mt_ (теоретически) выполняются в несколько раз быстрее «обычных» rand
C версии пыха 5 функции rand и mt_rand являются синонимами. Тыц-тыц.
Ну вот, устроили переполох.
Интересно, какой вариант предложит Young. :-)
Кстати, он же переполох и устроил :) Я потом не глядя на дату ссылки поверил в то, что всё плохо, а потом kp высказал такие же археологические суждения, и только Бутылкус вернул на путь истинный.
Ох уж эти ночные заморочки, не работает мозг как надо, выдумывает себе лабиринты незначительных зацепок и в них плутает, хотя стеночки-то низкие — подпрыгнуть только чтобы увидеть суть.
P.S. Хотя тесты не проводил, просто на веру всё. Ну не такая уж значительная это задача!
rand() убого реализована. Если работаете с чем-то серьезнее, чем выдача случайно страницы, используйте лучше mt_srand(time, microtime, ….) и mt_rand().
srand & mt_srand вызывать действительно не стоит, это делается автоматически, по поводу реализаций и отличий, вот набросал небольшой пример, я хз насколько он компетентен, но по-моему отличий нет
dumpz.org/53189/
$ php rand.php —width=500 —height=500 —limit=10000 —callback=rand —canvas=rand
www.picvalley.net/u/…
$ php rand.php —width=500 —height=500 —limit=10000 —callback=mt_rand —canvas=mt_rand
www.picvalley.net/u/…
Ничего ты увлёкся :) Да, сейчас явно rand() вполне прилично работает и нет никакого смысла заморачиваться с другими вариантами.
Да что же увлекся, даже приятно было пхп вспомнить, за несколько минут набросал…
Но радость была бы не полной, может не слишком красиво, но я дописал реализацию /dev/(u)random`ового генератора, и, интересный факт, во-первых, /dev/urandom работает НАМНОГО дольше штатных функций (хотя оно и ясно, наверное, все же ввод-вывод, еще и вычисления разные, но не думаю что можно слишком это оптимизировать)
Так вот, как не парадоксально, /dev/urandom дал худший результат, или я чего-то не понимаю? Не ожидал, не ожидал:
www.picvalley.net/u/…
Новая версия rand.php:
dumpz.org/53251/
Для тех кто не в курсе, /dev/random вообще основывается на пользовательском вводе, так что скорость его работы и замерять не стоит, дописывая эту заметку я так и не дождался окончания работы скрипта для колбека random, но не думаю что он слишком будет отличатся от штатных функций. Если дождусь, позже выложу…
Ха, очень интересные результаты. Мне вообще нравятся всякие такие исследования :) Думаю, худший результат может быть следствием как раз основы /dev/urandom на событиях системы. А в момент теста твоя машинка была сосредоточена в основном на обработке rand.php. Ну это так, предположение.
В общем, я бы на твоём месте попробовал ещё прогнать тот же тест, одновременно выполняя множество различных операций. Просмотр видео, браузинг, рассчёты какие-нибудь и т. п. Чем больше разнообразия — тем лучше.
Может я и не прав, но любопытно было бы проверить.
Нет, на событиях какраз /dev/random, а urandom не зависит. Я прогонял много раз, картина аналогична. Но тут надо понимать что не то что числа не случайны, просто числа более сосредоточены от лимитов, другими словами:
при лимите 0..10 будет больше чисел из диапазона 2..8, может это фишка такая, а может это из-за тех вычислений, я их спер со стека и особо не вдумывался :).
Я понял, тем не менее, правильный алгоритм на длительных дистанциях должен равномерно заполнять квадратик. Кстати, для задачи из темы заметки это в особенности важно.
Хотел проверить твой код, но у меня библиотеки для картинок в PHP нет, разбираться и ставить лень. Вернее, даже не столько лень, сколько надо другие дела делать, всё медленно у меня.
У меня aptitude install php5-gd, плохо когда это проблема в современном дистрибутиве. Я и сам пхп давно не пользовался а тут так все быстренько срослось.
О! А я сделал aptitude search php | grep image, не удивительно, что там не было. Тогда гляну может прямо сейчас. У меня сейчас всё ж вообще Debian Sid, куда уж современней :) Мы не ищем лёгких путей!
Блин, по зависимостям предлагает снести установленный и настроенный PHP и заменить его на более старую версию. Ну их нафиг, не буду заморачиваться всё же.
В sid они част будут меняться, если я еще не забыл дебиан :). И это же не смена версии, мажорной по крайней мере, это смена релиза скорей всего, настройки никуда не денутся, можешь смело накатывать. Да и спрашивать apt будет если настройки переписывать собрался.
Но я типа не настаиваю, просто gd нужный какбэ модуль…
Всё же запустил у себя твой код. Картинка примерно такая же — в углах насыщенность меньше. 500х500, лимит 10 тыс., скрипт работал 98 секунд.
Я почти уверен что разброс этот не из-за самого генератора а из-за вычислений приведения его в лимиты. Какое-то оно не верное, но уже нет желания разбираться :)