За последние 24 часа нас посетили 63108 программистов и 1740 роботов. Сейчас ищут 867 программистов ...

Выбор случайного значения с влиянием определенного шанса

Тема в разделе "PHP для новичков", создана пользователем Crystallon, 26 апр 2011.

  1. Crystallon

    Crystallon Активный пользователь

    С нами с:
    7 фев 2010
    Сообщения:
    61
    Симпатии:
    0
    Есть MySQL таблица такой структуры:
    id | factor
    1 | 1
    2 | 6
    3 | 4
    4 | 1
    5 | 3

    где:
    id - идентификатор(думаю это очевидно)
    factop - множитель шанса его выбора

    Нужно случайным образом выбрать один из id, но не совсем случайно, а с учетом множителя шанса его выбора, т.е. в данном примере у id 2 вероятность быть выбранным должна быть в 6 раз больше чем у id 1, в 2 раза больше чем у id 5 итд
    Моих знаний хватает только чтобы выбрать из этих 5 id случайный без влияющих факторов - rand(1, 5); подскажите как реализовать это с учетом шанса.
    Заранее спасибо за помощь.
     
  2. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
  3. YSandro

    YSandro Старожил

    С нами с:
    7 апр 2011
    Сообщения:
    2.523
    Симпатии:
    2
    Первый элемент будет иметь шанс 1/15, второй 6/15, третий 4/15... Можно продублировать второй элемент 5 раз (чтобы было 6), третий 3 раза (чтобы было 4), поставить их в ряд, потом перемешать. Потом рандомно выбираешь из 15-ти.
     
  4. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    YSandro
    ты это как придумал? тут шансы вобще отсутствуют. тут только некие гипотетические множители этих самых шансов.
     
  5. titch

    titch Активный пользователь

    С нами с:
    18 дек 2010
    Сообщения:
    847
    Симпатии:
    0
    когда-то я такое уже делал... дай бог памяти вспомнить, как это работало...
    PHP:
    1. <?
    2. mt_srand((int)(10000000*microtime(true)));
    3. $arr_Res = array('1'=>1,'2'=>6,'3'=>4,'4'=>1,'5'=>3);
    4. $int_adder = 0;
    5. foreach($arr_Res as $key=>$value){
    6.    $arr_Res[$key] += $int_adder;
    7.    $int_adder += $value;
    8. }
    9. $max = end($arr_Res);
    10. $arr_RevRes = array_reverse($arr_Res);
    11. $int_Grad = mt_rand(0,$max);
    12. $int_Pos = '';
    13. foreach($arr_RevRes as $key=>$value){
    14.    if($int_Grad>=$value){
    15.       $int_Pos = $key; break;
    16.    }
    17. }
    18. echo "id = $int_Pos";
    19.  
    за правильность не ручаюсь - только что написал
    ps: вероятность выпадения не должна равняться 0. иначе будет косяк. теоретически можно сразу удалить все элементы, где вероятность = 0 еще на этапе выборки из базы
     
  6. Crystallon

    Crystallon Активный пользователь

    С нами с:
    7 фев 2010
    Сообщения:
    61
    Симпатии:
    0
    Огромное спасибо, вроде как работает, только вот сколько не обновлял страницу со скриптом 5 никогда не выбрасывает не сморя на хороший шанс, а иногда еще и выбрасывает 0. Слушай если я не слишком многого прошу пожалуйста распиши каждую строчку кода в комменте(что она делает) просто мне бы надо понимать с чем я работаю, а в данном слуучае что-то не могу понять как это работает. =)
    Заранее спасибо.
     
  7. Crystallon

    Crystallon Активный пользователь

    С нами с:
    7 фев 2010
    Сообщения:
    61
    Симпатии:
    0
    Детальней изучив данный код сделал вывод что влияние шансов неправильное...
    Вот что получается в итоге array_reverse:
    $key=>$value
    0=>15

    1=>12

    2=>11

    3=>7

    4=>1

    дальше $int_Grad становится любым числом от 0 до 15 без всяких шансов
    Ищем $key $value которого больше или равен $int_Grad, он и будет выбран.
    Из этого следует что у четверки тут шанс быть выбранной 6 из 15(хотя должен быть 1 из 15), у тройки шанс 4 из 15(должен быть 4 из 15, тоесть в данном случае попали xD), у двойки шанс 2 из 15(должен быть 6 из 15, самый большой), у единицы шанс 3 из 15(должен быть 1 из 15, самый маленький), и соответственно нет пятерки и появился ноль.
     
  8. titch

    titch Активный пользователь

    С нами с:
    18 дек 2010
    Сообщения:
    847
    Симпатии:
    0
    а... ну ессно. я писал это на сон грядущий. передайте в array_reverse еще один параметр, чтобы сохранить ключи. array_reverse($arr_Res,true);
    остальное в порядке вроде как
     
  9. Crystallon

    Crystallon Активный пользователь

    С нами с:
    7 фев 2010
    Сообщения:
    61
    Симпатии:
    0
    Это я уже понял и сделал) тока это все проблемы не решило:
    $int_Pos = $key+1; break;
    Я до сих пор не совсем разобрался как именно работает этот код(главный смысл не пойму как происходит расчет процентов) т.к. когда я пытаюсь запарится и понять это я сразу запутываюсь xD...вобщем:
    если ставить $int_Pos = $key; break; то расчет идет неправильно, я думал уж все, не заработает, потом присмотревшись обнаружил что разница между value совпадает с необходимыми множителями шанса если смотреть значение для нужного key "на строчку выше". Вобщем теперь почти все работает как надо, но в том то и проблема что почти все - из за +1 может быть выведен key на 1 больше чем максимальный, и key №1 не может быть вызван(в принципе это не столь серьезно, я могу просто зарезервировать key 1 для пустого значения чтобы его не занял пользователь и если будет выбран кей max+1 запускать скрипт по второму кругу чтобы получить другое значение...но все же хотелось бы без этого, можно ли как-то исправить?
    И еще такая проблема:
    $arr_Res = array('1'=>1,'2'=>6,'3'=>4,'4'=>1,'5'=>3);
    Как мне заполнить такой массив данными из MySQL БД? mysql_fetch_array выводит какую-то хрень...
     
  10. MiksIr

    MiksIr Активный пользователь

    С нами с:
    29 ноя 2006
    Сообщения:
    2.339
    Симпатии:
    44
    Вот почему человеу нужно давать идею, а реализует он ее пусть сам. А то разверни, в рот положи - а он спросит как сосать.

    Представьте ваши значения серией отрезков на одной линии. Длина отрезка - это ваш "фактор". Т.е. общая длина будет равна сумме всех факторов, т.е. 15. Берем случайное число от 1 до 15 и смотрим, в какой отрезок оно попадет - это и будет искомое id.

    Вперед, пишите код.
     
  11. Crystallon

    Crystallon Активный пользователь

    С нами с:
    7 фев 2010
    Сообщения:
    61
    Симпатии:
    0
    В данный момент все итак работает по этому принципу) правда ваши слова меня все равно натолкнули на мысль =)
    Переворачивание массива было излишним действием... Теперь в общем все работает отлично, но последний вопрос все равно остался(яндекс адекватного ответа не дал, ну либо я хреново искал, иначе бы не писал):
    $arr_Res = array('1'=>1,'2'=>6,'3'=>4,'4'=>1,'5'=>3);
    Как мне заполнить такой массив данными из MySQL БД? Тут уже нужен конкретный код а не идея)
     
  12. MiksIr

    MiksIr Активный пользователь

    С нами с:
    29 ноя 2006
    Сообщения:
    2.339
    Симпатии:
    44
    И тут все просто. Идете на страничку описания функции в документации, смотрите, что она делает, смотрите примеры... и потихоньку понимаете, что же нужно делать.
     
  13. Crystallon

    Crystallon Активный пользователь

    С нами с:
    7 фев 2010
    Сообщения:
    61
    Симпатии:
    0
    Ок, на страничку какой функции? И вообще этот форум создан для того чтобы люди задавали вопросы а другие ЖЕЛАЮЩИЕ люди на них отвечали а не посылали читать макулатуру, разве я не прав? Я задал конкретный вопрос, если у вас нет желания на него отвечать пройдите мимо.
     
  14. MiksIr

    MiksIr Активный пользователь

    С нами с:
    29 ноя 2006
    Сообщения:
    2.339
    Симпатии:
    44
    mysql_fetch_array

    Ну жди пока тебе разжуют и в рот положат, раз своей головы бог не дал.
     
  15. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    Crystallon
    что у вас эти цифирьки означают? это вероятности?
     
  16. Crystallon

    Crystallon Активный пользователь

    С нами с:
    7 фев 2010
    Сообщения:
    61
    Симпатии:
    0
    Да, вероятность, но это уже неважно, я все сделал)
    Огромнейшее спасибище titch'у! =)
     
  17. titch

    titch Активный пользователь

    С нами с:
    18 дек 2010
    Сообщения:
    847
    Симпатии:
    0
    да не за что.
     
  18. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    Crystallon
    ну просто мне интересно. а вероятность в чем? в процентах?
     
  19. titch

    titch Активный пользователь

    С нами с:
    18 дек 2010
    Сообщения:
    847
    Симпатии:
    0
    igordata, в долях.
    вот есть у тебя 3 яблока и 7 бананов в мешке. вероятность вытянуть наугад банан - 7/10. кидаем туда еще 10 помидоров и вероятность вытянуть банан уже 7/20. помидор соответственно 1/2, а яблоко - 3/20. эластичность такого подхода в том, что если ты добавляешь еще новые элементы, то автоматически изменяется вероятность выпадения всех остальных элементов.
     
  20. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    была такая мысль, но мне показалось не оч. удобно управлять.