За последние 24 часа нас посетили 15077 программистов и 1654 робота. Сейчас ищут 911 программистов ...

mt_rand

Тема в разделе "Прочее", создана пользователем Kreker, 3 янв 2012.

  1. Kreker

    Kreker Старожил

    С нами с:
    8 апр 2007
    Сообщения:
    5.433
    Симпатии:
    0
    Здравствуйте, коллеги! :lol:
    Никто из вас не замечал каких-либо странностей в работе функции mt_rand?

    Дело вот в чем. У нас есть игра. Мы добавили сервер и перенесли основные вычисления туда (там стоит 64х php 5.3.х). После чего игроки стали жаловаться на то, что поведение в игре изменилось.
    У нас во всех действиях заложена вероятность. Допустим, когда слабый соперник сражается с сильным, то у слабого 1/2000 выиграть:
    PHP:
    1. <?php
    2. $rnd = mt_rand(1,100000); if ($rnd < 50) { слабый игрок выиграл действие }.
    Так вот, проблема в том, что пользователи начали жаловаться, что слабый игрок может выиграть несколько действий у сильного подряд. То есть, получается, что рандом несколько раз подряд бьет в диапазон до 50!
    Я пытался тестировать локально (на 32х php 5.2.x), однако не находил такого близкого разброса.

    На днях на форуме (уже на другом сервере) я сделал случайную замену аватарак на новогодние картинки:
    PHP:
    1. <?php
    2. $rnd = mt_rand(1, 39);
    3.  
    4. if ($rnd < 15) {
    5.     //Реальный аватар юзера
    6. }
    7. else {
    8.     'images/snowman'.floor($rnd/10).'.png' //один из трех подставных
    9. }
    И здесь я заметил странности:
    1) Родные аватары попадаются редко, всегда заменено большинство. (хотя, по формуле большинство и должно быть, но не все же)
    2) Очень часто подставные выпадают пачками по 2-3 штуки, то есть, 3 штуки snowman3, потом 3 штуки snowman2

    Мне одному кажется, что рандом работает слишком кучно? Как менять кучность? Сидом? :? Или может использовать системный рандом?
     
  2. igordata

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

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    а рандом в пхп разве не стремится к нормальному? =) (шоб я знал что это значит)
     
  3. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    Это когда в диапазоне от 1 до 100, 50 выпадает много чаще, чем 1. Кто-то писал что у rand() есть такая склонность, но mt_rand по-идее лучше. Вообще в диапазоне от 1 до 100000 просто невероятно, чтобы был приоритет у диапазона <50. Но вероятность, что так выпадет несколько раз подряд, все же есть. Если у вас 10000 игроков делает 100 боев в день, то из этого миллиона кому-то всё же выпадет <50 несколько раз подряд. Он и пожалуется.
     
  4. igordata

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

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    [vs]
    Мт-ранд написано в доках что в четыре раза быстрее. Про лучче там ни слова.
     
  5. Elkaz

    Elkaz Старожил
    Команда форума Модератор

    С нами с:
    26 июн 2006
    Сообщения:
    3.373
    Симпатии:
    0
    Адрес:
    Баку, Азербайджан
    elkin@elkin-N53SV ~ $ php -r 'for ($i = 0; $i < 100; $i++){ echo (mt_rand (1, 100000) < 50) ? "yes\n" : "no\n"; }'
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no
    no



    100 можно заменить на 1 000 000 — у меня ни одного «yes» не выпало.
    Вот, к примеру, на миллион:

    elkin@elkin-N53SV ~ $ php -r '$counter = 0; for ($i = 0; $i < 100000; $i++){ (mt_rand (1, 100000) < 50) ? $counter++ : ""; } echo "Меньше 50 выпало $counter раз\n";'

    Меньше 50 выпало 52 раз


    elkin@elkin-N53SV ~ $ php -r '$counter = 0; for ($i = 0; $i < 100000; $i++){ (mt_rand (1, 100000) < 50) ? $counter++ : ""; } echo "Меньше 50 выпало $counter раз\n";'

    Меньше 50 выпало 39 раз


    elkin@elkin-N53SV ~ $ php -r '$counter = 0; for ($i = 0; $i < 100000; $i++){ (mt_rand (1, 100000) < 50) ? $counter++ : ""; } echo "Меньше 50 выпало $counter раз\n";'

    Меньше 50 выпало 47 раз


    elkin@elkin-N53SV ~ $ php -r '$counter = 0; for ($i = 0; $i < 1000000; $i++){ (mt_rand (1, 100000) < 50) ? $counter++ : ""; } echo "Меньше 50 выпало $counter раз\n";'

    Меньше 50 выпало 496 раз


    elkin@elkin-N53SV ~ $ php -r '$counter = 0; for ($i = 0; $i < 1000000; $i++){ (mt_rand (1, 100000) < 50) ? $counter++ : ""; } echo "Меньше 50 выпало $counter раз\n";'

    Меньше 50 выпало 478 раз


    В среднем шанс получается 1/2000.
    PHP 5.3.6-13ubuntu3.3 with Suhosin-Patch (cli) (built: Dec 13 2011 18:18:37)
    Linux Mint x64

    elkin@elkin-N53SV ~ $ php -r '$counter = 0; for ($i = 0; $i < 1000000; $i++){ (mt_rand (1, 100000) < 50) ? $counter++ : ""; } echo "Меньше 50 выпало $counter раз\n";'

    Меньше 50 выпало 519 раз


    elkin@elkin-N53SV ~ $ php -r '$counter = 0; for ($i = 0; $i < 1000000; $i++){ (mt_rand (1, 100000) < 50) ? $counter++ : ""; } echo "Меньше 50 выпало $counter раз\n";'

    Меньше 50 выпало 558 раз


    elkin@elkin-N53SV ~ $ php -r '$counter = 0; for ($i = 0; $i < 1000000; $i++){ (mt_rand (1, 100000) < 50) ? $counter++ : ""; } echo "Меньше 50 выпало $counter раз\n";'

    Меньше 50 выпало 531 раз


    elkin@elkin-N53SV ~ $ php -r '$counter = 0; for ($i = 0; $i < 1000000; $i++){ (mt_rand (1, 100000) < 50) ? $counter++ : ""; } echo "Меньше 50 выпало $counter раз\n";'

    Меньше 50 выпало 515 раз


    elkin@elkin-N53SV ~ $ php -r '$counter = 0; for ($i = 0; $i < 1000000; $i++){ (mt_rand (1, 100000) < 50) ? $counter++ : ""; } echo "Меньше 50 выпало $counter раз\n";'

    Меньше 50 выпало 471 раз


    elkin@elkin-N53SV ~ $ php -r '$counter = 0; for ($i = 0; $i < 1000000; $i++){ (mt_rand (1, 100000) < 50) ? $counter++ : ""; } echo "Меньше 50 выпало $counter раз\n";'

    Меньше 50 выпало 479 раз


    elkin@elkin-N53SV ~ $ php -r '$counter = 0; for ($i = 0; $i < 1000000; $i++){ (mt_rand (1, 100000) < 50) ? $counter++ : ""; } echo "Меньше 50 выпало $counter раз\n";'

    Меньше 50 выпало 498 раз


    elkin@elkin-N53SV ~ $ php -r '$counter = 0; for ($i = 0; $i < 1000000; $i++){ (mt_rand (1, 100000) < 50) ? $counter++ : ""; } echo "Меньше 50 выпало $counter раз\n";'

    Меньше 50 выпало 475 раз


    elkin@elkin-N53SV ~ $ php -r '$counter = 0; for ($i = 0; $i < 1000000; $i++){ (mt_rand (1, 100000) < 50) ? $counter++ : ""; } echo "Меньше 50 выпало $counter раз\n";'

    Меньше 50 выпало 512 раз
     
  6. Kreker

    Kreker Старожил

    С нами с:
    8 апр 2007
    Сообщения:
    5.433
    Симпатии:
    0
    Я такие же тесты локально проводил и у меня такой же результат был.