How random is PHP's shuffle function?
Does anyone know what's the randomness of PHP's shuffle()
f开发者_运维百科unction? Does it depend on the operating system?
Does it use PHP's own seeder?
Is it possible to use mt_rand()
as generator?
shuffle()
function is based on the same generator as rand()
, which is the system generator based on linear congruential algorithm. This is a fast generator, but with more or less randomness. Since PHP 4.2.0, the random generator is seeded automatically, but you can use srand()
function to seed it if you want.
mtrand()
is based on Mersenne Twister algorithm, which is one of the best pseudo-random algorithms available. To shuffle an array using that generator, you'd need to write you own shuffle function. You can look for example at Fisher-Yates algorithm. Writing you own shuffle function will yield to better randomness, but will be slower than the builtin shuffle function.
Update for PHP 7.1
Since the rng_fixes rfc was implemented for PHP 7.1, the implementation of shuffle
now utilizes the Mersenne Twister PRNG (i.e. it uses mt_rand
and is affected by calling mt_srand
).
The legacy system PRNG (rand
) is no longer available; the functions rand
and srand
are in fact aliased to their mt_
equivalents.
Based on Mirouf's answer (thank you so much for your contribution)... I refined it a little bit to take out redundant array counting. I also named the variables a little differently for my own understanding.
If you want to use this exactly like shuffle(), you could modify the parameter to be passed by reference, i.e. &$array, then make sure you change the return to simply: "return;" and assign the resulting random array back to $array as such: $array = $randArr; (Before the return).
function mt_shuffle($array) {
$randArr = [];
$arrLength = count($array);
// while my array is not empty I select a random position
while (count($array)) {
//mt_rand returns a random number between two values
$randPos = mt_rand(0, --$arrLength);
$randArr[] = $array[$randPos];
/* If number of remaining elements in the array is the same as the
* random position, take out the item in that position,
* else use the negative offset.
* This will prevent array_splice removing the last item.
*/
array_splice($array, $randPos, ($randPos == $arrLength ? 1 : $randPos - $arrLength));
}
return $randArr;
}
It's random just like rand()
;
And as PHP style you don't need to seed
mt_rand()
Generates a random number.
shuffle()
Randomizes an array. It also generates new keys in the array rather than just rearranging the old ones.
If you want to seed in PHP you would have used mt_strand()
.
However, since PHP 4.2.0 seeding is done automatically in PHP when you call mt_rand.
Works with associative and numeric arrays:
function mt_shuffle_array($array) {
$shuffled_array = [];
$arr_length = count($array);
if($arr_length < 2) {
return $array;
}
while($arr_length) {
--$arr_length;
$rand_key = array_keys($array)[mt_rand(0, $arr_length)];
$shuffled_array[$rand_key] = $array[$rand_key];
unset($array[$rand_key]);
}
return $shuffled_array;
}
$array = [-2, -1, 'a' => '1', 'b' => '2', 'c' => '3', 11, 'd' => '4', 22];
$shuffled_array = mt_shuffle_array($array);
I've created a function who sort my array randomly.
/**
* Build a random array
*
* @param mixed $array
*
* @return array
*/
function random_array($array) {
$random_array = array();
// array start by index 0
$countArray = count($array) - 1;
// while my array is not empty I build a random value
while (count($array) != 0) {
//mt_rand return a random number between two value
$randomValue = mt_rand(0, $countArray);
$random_array[] = $array[$randomValue];
// If my count of my tab is 4 and mt_rand give me the last element,
// array_splice will not unset the last item
if(($randomValue + 1) == count($array)) {
array_splice($array, $randomValue, ($randomValue - $countArray + 1));
} else {
array_splice($array, $randomValue, ($randomValue - $countArray));
}
$countArray--;
}
return $random_array;
}
It's not the best way to do that but when I've used the function shuffle, it was always returning a random array in the same order. If this could help someone, I will be happy !
精彩评论