PHP的shuffle函数有多随机?

18

谁知道PHP的shuffle()函数有多随机?它是否取决于操作系统?它是否使用PHP自己的种子生成器?

可以将mt_rand()用作生成器吗?


1
对于大多数应用程序来说,它已经足够随机了。但它并不具备密码学安全性。 - NikiC
7个回答

16

shuffle() 函数基于与 rand() 相同的生成器,即基于线性同余算法的系统生成器。这是一个快速的生成器,但其随机性更多或更少。自PHP 4.2.0起,随机生成器会自动初始化种子,但如果您需要,可以使用 srand() 函数进行手动初始化。

mtrand() 基于Mersenne Twister算法,是可用的最佳伪随机算法之一。要使用该生成器对数组进行洗牌,您需要编写自己的shuffle函数。你可以参考Fisher-Yates算法的示例。编写自己的shuffle函数将产生更好的随机性,但比内置的shuffle函数慢。


7

PHP 7.1更新

自从针对PHP 7.1实施了rng_fixes rfcshuffle的实现现在使用梅森旋转算法伪随机数生成器(即它使用mt_rand并受到调用mt_srand的影响)。

传统系统的伪随机数生成器(rand)不再可用;函数randsrand实际上被别名为它们的mt_等效函数。


6
基于Mirouf的回答(非常感谢您的贡献)......我对其进行了一些修改,以消除冗余的数组计数。我还为了自己的理解,稍微改变了一下变量的命名。
如果您想完全像shuffle()函数一样使用它,您可以修改参数传递的方式,即将$array作为引用传递,然后确保将返回值更改为简单的:"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;
}

4

它就像rand()一样随机;

而且按照PHP的风格,你不需要进行种子设置。


2
mt_rand()

生成一个随机数。

shuffle()

随机化一个数组。它会生成新的键而不仅仅是重新排列旧的键。

如果你想在PHP中播种,你可以使用mt_strand()

然而,自从PHP 4.2.0以后,在调用mt_rand时,PHP会自动进行播种。


1
所以,基本上如果你想使用mt_rand()作为生成器,你必须自己编写shuffle()函数?或者如果已经使用了mt_rand(),那么shuffle会使用它吗? - Sinan

2

可以处理关联数组和数字数组:

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);

enter image description here


0
我创建了一个函数,可以随机排序我的数组。
/**
 * 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函数时,它总是以相同的顺序返回随机数组。 如果这能帮助到某人,我会很高兴!


你应该在每次迭代中使用array_splice并更新countArray。使用unset会在数组中留下空隙,如果你随机选择了已经unset的索引之一,那么你将会向输出数组中添加一个NULL。 - FishFace

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接