Answer the question
In order to leave comments, you need to log in
How can you achieve diversity randomness in PHP?
Hello!
I needed random numbers within a certain interval.
I used mt_rand(322, 595);
But each time the numbers are about four hundred: 423, 436, 431, 451.
Is it possible to somehow diversify this randomness?
Answer the question
In order to leave comments, you need to log in
From time to time (randomly: 0/1) shifting the input range by one to the right and not shifting, we change the bits used in the original mt_rand() function. In this way, very high quality pseudo-random output data is achieved.
If you need to "dilute" the randomness even more: you just need to recurse the current function and call the required number of times (more than 8 - I do not recommend, because narrowing / loss of scatter is possible).
<?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
)
Randomness cannot be diversified, because in it, each next drop-down number
does not depend in any way on what fell out earlier.
It is intuitively clear that you want each next number, most likely, to be different from the previous one, the more, the better. But it's not really random anymore.
You can mimic this behavior. The easiest way is to hard ban closer than, say, 40 from the previous one.
This means that a segment with a length falls out of the segment of values 40 + 1 + 40 = 81
. The first call will return a fair-random mt_rand(322, 595)
A, the next only mt_rand(322, 514)
And it will be necessary to correct it, depending on the previous one. Rough like this:
$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;
// ...
1) First you should use random_int, instead of deprecated mt_rand
2) End =)
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question