Как можно добиться разнообразия рандомности в PHP?

Всем привет!
Мне нужны были случайные числа на определенном промежутке.
Я использовал метод mt_rand(322, 595);
Но каждый раз числа получаются около четырех ста: 423, 436, 431, 451.
Возможно ли как то разнообразить эту рандомность?
  • Вопрос задан
  • 529 просмотров
Решения вопроса 1
xmoonlight
@xmoonlight Куратор тега PHP
https://sitecoder.blogspot.com
Время от времени (случайным образом: 0/1) сдвигая входной диапазон на единицу вправо и не сдвигая, мы меняем используемые биты в исходной функции mt_rand(). Таким образом, достигаются очень качественные псевдо-случайные выходные данные.

Если необходимо ещё более "разбавить" случайность: нужно просто сделать рекурсию текущей функции и вызвать необходимое количество раз (более 8 - не рекомендую, т.к. возможно сужение/потеря разброса).
<?php
//////RANDOM FUNCTION//////
function myRand($from,$to) {
	$to+=1;
	$dist=$to-$from;
	$i=mt_rand(0,1);
	$r=$from+mt_rand($from+$i%2, $to-($i+1)%2)%$dist;
	return $r;
}

/////MAIN//////
$from=300;
$to=600;

for ($i = 0; $i <= 12; $i++) {
 echo myRand($from,$to)." ";
}
//473 315 459 597 555 508 448 337 455 348 329 462 309
//316 500 464 546 402 411 431 581 382 351 521 567 449
//585 312 416 391 360 385 598 399 495 443 561 350 441 
//477 589 429 318 558 428 315 441 432 420 324 578 432 
//465 581 378 512 376 563 415 307 347 310 594 364 388

Проверка монотонности разброса:
<?php
//////RANDOM FUNCTION//////
function myRand($from,$to) {
	$to+=1;
	$dist=$to-$from;
	$i=mt_rand(0,1);
	$r=$from+mt_rand($from+$i%2, $to-($i+1)%2)%$dist;
	return $r;
}

/////MAIN//////
$from=1;
$to=10;
$stat=[];
for ($i = 0; $i <= 10000000; $i++) {
 $stat[myRand($from,$to)]++;
}
asort($stat);
print_r($stat);


Результат:
Array
(
    [3] => 998512
    [8] => 998546
    [5] => 999444
    [7] => 999467
    [10] => 999749
    [1] => 999845
    [2] => 1000340
    [6] => 1001172
    [9] => 1001192
    [4] => 1001734
)
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
sergiks
@sergiks Куратор тега PHP
♬♬
Рандомность нельзя разнообразить, т.к. в ней каждое следующее выпадающее число
никак не зависит от того, что выпадало ранее.

Интуитивно понятно, что хочется, чтобы каждое следующее число, скорее всего, отличалось бы от предыдущего чем больше, тем лучше. Но это уже не настоящая рандомность.

Можно сымитировать такое поведение. Проще всего жёстко запретить ближе, чем, допустим, 40 от предыдущего.
Значит, из отрезка значений выпадает отрезок длиной 40 + 1 + 40 = 81
Первый вызов вернёт честно-случайное mt_rand(322, 595)
А следующий только mt_rand(322, 514)
И надо будет его скорректировать, в зависимости от предыдущего. Грубо, так:
$a = 322;
$b = 595;
$m = 40;

// первый раунд
$rnd = mt_rand($a, $b);
$prev = $rnd;
// ... что-то происходит

// второй и последующие раунды
$rnd = mt_rand($a, $b - 2 * $m - 1);
if ($rnd > $prev - $m) $rnd += 2 * $m + 1;
if ($rnd > $b) $rnd -= ($b - $a);
$prev = $rnd;
// ...
Ответ написан
SerafimArts
@SerafimArts
Senior HTML Developer
1) Для начала следует использовать random_int, вместо устаревшей mt_rand
2) Конец =)
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы