【发布时间】:2011-08-07 08:23:55
【问题描述】:
有谁知道 PHP 的 shuffle() 函数的随机性是什么?它取决于操作系统吗?
它是否使用 PHP 自己的播种机?
是否可以使用mt_rand() 作为生成器?
【问题讨论】:
-
它对于大多数应用程序来说足够随机。但它在密码学上并不安全。
有谁知道 PHP 的 shuffle() 函数的随机性是什么?它取决于操作系统吗?
它是否使用 PHP 自己的播种机?
是否可以使用mt_rand() 作为生成器?
【问题讨论】:
shuffle()函数基于与rand()相同的生成器,即基于linear congruential algorithm的系统生成器。这是一个快速生成器,但或多或少具有随机性。自 PHP 4.2.0 起,随机生成器是自动播种的,但您可以根据需要使用srand() 函数来播种。
mtrand() 基于Mersenne Twister algorithm,这是可用的最佳伪随机算法之一。要使用该生成器对数组进行随机播放,您需要编写自己的随机播放函数。例如,您可以查看Fisher-Yates algorithm。编写自己的 shuffle 函数会产生更好的随机性,但会比内置的 shuffle 函数慢。
【讨论】:
根据 Mirouf 的回答(非常感谢您的贡献)...我对其进行了一些改进以消除冗余数组计数。为了我自己的理解,我对变量的命名也略有不同。
如果你想像 shuffle() 一样使用它,你可以修改要通过引用传递的参数,即 &$array,然后确保将 return 更改为简单的:“return;”并将生成的随机数组分配回 $array ,如下所示: $array = $randArr; (返回前)。
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;
}
【讨论】:
由于rng_fixes rfc 是为 PHP 7.1 实现的,shuffle 的实现现在使用 Mersenne Twister PRNG(即它使用 mt_rand 并受到调用 mt_srand 的影响)。
旧系统 PRNG (rand) 不再可用; rand 和 srand 函数实际上是它们的 mt_ 等效项的别名。
【讨论】:
和rand()一样是随机的;
而且作为 PHP 风格,您不需要播种
【讨论】:
mt_rand()
生成一个随机数。
shuffle()
随机化一个数组。它还会在数组中生成新键,而不仅仅是重新排列旧键。
如果你想在 PHP 中播种,你会使用 mt_strand()。
但是,由于 PHP 4.2.0 播种是在您调用 mt_rand 时在 PHP 中自动完成的。
【讨论】:
适用于关联数组和数值数组:
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);
【讨论】:
我创建了一个随机排序数组的函数。
/**
* 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;
}
这不是最好的方法,但是当我使用函数 shuffle 时,它总是以相同的顺序返回一个随机数组。如果这可以帮助某人,我会很高兴!
【讨论】: