Евгений Степанищев

Я — эксперт в области разработки веб-приложений и безопасности в интернете. Каждый месяц мой блог посещают около 90 тысяч человек. Работаю техническим директором в «Системах документооборота», занимаюсь электронным правительством.

Генерация «трафки™» или распределение по весам

Дима Смирнов применил интересное решение для генерации «трафок» на «Блоговаре»:
$rb   = str_pad (decbin (mt_rand (0,64)),6,"0", STR_PAD_LEFT);
$herb = (int) strpos ($rb, "1");
Смысл в том, что каждое следующее значение должно выпадать с вдвое меньшей вероятностью, чем предыдущее. Пока я спал, мне пришло в голову довольно забавное решение на ту же тему. Оно быстрее примерно на 30%, не обладает ограничением на размер и точнее вычисляет вероятности (у Димы «трафка» не выпадает с вероятностью примерно 52%), но не решает задачу полностью. Кто скажет в чём разница, не запуская код?
for ($i = 5; $i && mt_rand(0, 1); --$i);
14 ноября 2007 10:50

Ramon (rembish.ru)
14 ноября 2007, 12:54

У Вас веса в обратную сторону: пятерка выпадает чаще, чем ноль.
И, кроме того, у Вас правильно обрабатывается оставшийся вес - у Димы, например, туда отводится ~1,5625% у вас должные оставшиеся ~3,125%.

bolk (bolknote.ru)
14 ноября 2007, 13:11

Второе — верно, но вы запускали, судя по всему, а это не так интересно. То, что всё идёт в обратную сторону решается реверсом цикла или вычитанием из пяти.

Ramon (rembish.ru)
14 ноября 2007, 13:19

Вообще, и да, и нет. Я написал свой вариант через array_map/array_fill и уже там углядел, что проценты по идее теряются - оттуда возникла идея, которую визуально проверил на Вашем примере.

nudnik.ru (nudnik.ru)
14 ноября 2007, 13:22

Разница в том. что твое решение "не решает задачу полностью", geeze.

nudnik.ru (nudnik.ru)
14 ноября 2007, 13:26

У меня, кстати, в работающем коде стоит (1,63) вместо (0,64).

Но я побоялся, что люди не поймут, поэтому написал "более понятно".

Ramon (rembish.ru)
14 ноября 2007, 13:28

stats_rand_gen_normal?

bolk (bolknote.ru)
14 ноября 2007, 13:57

array_fill можно, да, но решение хотелось сделать неочевидным :)

bolk (bolknote.ru)
14 ноября 2007, 14:12

Дим, конечно, мой пример задачу не решает, тут достоинства твоего очевидны :) Просто приснился забавный пример. Кстати говоря, вряд ли все могут сказать сходу как работает то и другое и почему результаты в «хвосте» разные :) И откуда взялись 2% — тоже :)

Ramon (rembish.ru)
14 ноября 2007, 14:40

Вот, кстати, мой вариант: strpos(implode("", array_map("mt_rand", array_fill(0, 6, 0), array_fill(0, 6, 1))), "1");

bolk (bolknote.ru)
14 ноября 2007, 16:31

Мда, в каком-нибудь Perl или Ruby это было бы куда изящнее :)

Ваше имя или адрес блога (можно OpenID):

Текст вашего комментария, не HTML:

Кому бы вы хотели ответить (или кликните на его аватару)

Подсказка по написанию комментария

В комментариях можно применять следующую специальную разметку:

  • слово, обрамлённое в «звёздочки» выделяется *жирным*
  • ссылка становится ссылкой: http://bolknote.ru
  • ссылка в скобках также становится ссылкой, закрывающая скобка не захватывается: (http://bolknote.ru)
  • каждую строку цитаты следует начинать со знака «больше»:
    > это цитата
    > из двух строк
  • можно вставить картинку, залитую на один из сервисов: «Яндекс.Фотки», «Фликр» или «Пикплз». Для этого нужно вставить на страницу полный адрес вашей картинки на сервисе, он превратится в картинку:

    http://fotki.yandex.ru/users/bolknote/view/274311?page=3