Здравствуйте, коллеги! :lol: Никто из вас не замечал каких-либо странностей в работе функции mt_rand? Дело вот в чем. У нас есть игра. Мы добавили сервер и перенесли основные вычисления туда (там стоит 64х php 5.3.х). После чего игроки стали жаловаться на то, что поведение в игре изменилось. У нас во всех действиях заложена вероятность. Допустим, когда слабый соперник сражается с сильным, то у слабого 1/2000 выиграть: PHP: <?php $rnd = mt_rand(1,100000); if ($rnd < 50) { слабый игрок выиграл действие }. Так вот, проблема в том, что пользователи начали жаловаться, что слабый игрок может выиграть несколько действий у сильного подряд. То есть, получается, что рандом несколько раз подряд бьет в диапазон до 50! Я пытался тестировать локально (на 32х php 5.2.x), однако не находил такого близкого разброса. На днях на форуме (уже на другом сервере) я сделал случайную замену аватарак на новогодние картинки: PHP: <?php $rnd = mt_rand(1, 39); if ($rnd < 15) { //Реальный аватар юзера } else { 'images/snowman'.floor($rnd/10).'.png' //один из трех подставных } И здесь я заметил странности: 1) Родные аватары попадаются редко, всегда заменено большинство. (хотя, по формуле большинство и должно быть, но не все же) 2) Очень часто подставные выпадают пачками по 2-3 штуки, то есть, 3 штуки snowman3, потом 3 штуки snowman2 Мне одному кажется, что рандом работает слишком кучно? Как менять кучность? Сидом? :? Или может использовать системный рандом?
Это когда в диапазоне от 1 до 100, 50 выпадает много чаще, чем 1. Кто-то писал что у rand() есть такая склонность, но mt_rand по-идее лучше. Вообще в диапазоне от 1 до 100000 просто невероятно, чтобы был приоритет у диапазона <50. Но вероятность, что так выпадет несколько раз подряд, все же есть. Если у вас 10000 игроков делает 100 боев в день, то из этого миллиона кому-то всё же выпадет <50 несколько раз подряд. Он и пожалуется.
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 раз