使用种子随机化PHP数组?

cwd*_*cwd 34 php arrays random seed

我正在寻找一个函数,我可以在PHP中传递数组和种子并返回一个"随机"数组.如果我再次传递相同的数组和相同的种子,我会得到相同的输出.

我试过这段代码

//sample array
$test = array(1,2,3,4,5,6);
//show the array
print_r($test);

//seed the random number generator
mt_srand('123');
//generate a random number based on that
echo mt_rand();
echo "\n";

//shuffle the array
shuffle($test);

//show the results
print_r($test);

但它似乎没有用.有关最佳方法的任何想法吗?

这个问题围绕这个问题跳舞,但它已经过时了,没有人提供如何做到的实际答案:我可以通过提供种子随机化数组并获得相同的顺序吗?- "是的,但是怎么?

更新

到目前为止,答案适用于PHP 5.1和5.3,但不适用于5.2.就是这样,我想运行它的机器正在使用5.2.

任何人都可以不使用mt_rand给出一个例子吗?它在php 5.2中被"破坏",因为它不会根据相同的种子给出相同的随机数序列.请参阅php mt_rand页面错误跟踪器以了解此问题.

And*_*zlo 46

抱歉,相应的文档中,随机播放功能会自动播种.

通常情况下,您不应该尝试使用自己的算法来随机化事物,因为它们很可能是有偏见的.已知Fisher-Yates 算法既高效又无偏见:

function fisherYatesShuffle(&$items, $seed)
{
    @mt_srand($seed);
    for ($i = count($items) - 1; $i > 0; $i--)
    {
        $j = @mt_rand(0, $i);
        $tmp = $items[$i];
        $items[$i] = $items[$j];
        $items[$j] = $tmp;
    }
}
Run Code Online (Sandbox Code Playgroud)

示例(PHP 5.5.9):

php > $original = array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
php > $shuffled = (array)$original;
php > fisherYatesShuffle($shuffled, 0);
php > print_r($shuffled);
Array
(
    [0] => 6
    [1] => 0
    [2] => 7
    [3] => 2
    [4] => 9
    [5] => 3
    [6] => 1
    [7] => 8
    [8] => 5
    [9] => 4
)
php > $shuffled = (array)$original;
php > fisherYatesShuffle($shuffled, 0);
php > print_r($shuffled);
Array
(
    [0] => 6
    [1] => 0
    [2] => 7
    [3] => 2
    [4] => 9
    [5] => 3
    [6] => 1
    [7] => 8
    [8] => 5
    [9] => 4
)
Run Code Online (Sandbox Code Playgroud)

  • @drchuck.它是可预测的,与5.2.1之前的PHP版本产生的顺序不同.值得注意的是. (3认同)
  • 这是一个很好的解决方案,但自 PHP 5.3.1 起, mt_srand “相同的种子不再产生与以前版本中相同的值序列。” - 所以这不再是一个可预测的洗牌。我发现并使用了 Mersenne_Twister 类而不是 mt_srand 和 mt_rand,这种方法给了我一个可预测/可重复的洗牌。 (2认同)

Gum*_*mbo 20

您可以使用array_multisort第二个mt_rand值数组来排序数组值:

$arr = array(1,2,3,4,5,6);

mt_srand('123');
$order = array_map(create_function('$val', 'return mt_rand();'), range(1, count($arr)));
array_multisort($order, $arr);

var_dump($arr);
Run Code Online (Sandbox Code Playgroud)

$order是一个mt_rand长度相同的数组$arr.array_multisort排序的值$order,并命令的元素$arr根据的值的顺序$order.

  • 请使用 `function ($val) { return mt_rand(); }` 而不是 `create_function('$val', 'return mt_rand();')` (4认同)
  • 实际上,这个答案可能不适用于所有版本的PHP.我刚注意到运行5.2.17的服务器将为$ order变量创建一个随机数字序列.这里也有一个注释:自5.2.1以来,PHP中的Mersenne Twister实现现在使用Richard Wagner的新种子算法.相同的种子不再产生与先前版本中相同的值序列.预计这种行为不会再次发生变化,但依赖它仍被认为是不安全的. - http://php.net/manual/en/function.mt-srand.php (2认同)
  • @cwd:那么你可能不得不坚持使用旧的'rand`和`srand`. (2认同)
  • 自 PHP 7.2.0 起,`create_function` 已被弃用 (2认同)

Spu*_*ley 5

您遇到的问题是 PHP 内置了两个随机数生成器。

shuffle()命令不使用mt_rand()随机数生成器;它使用较旧的rand()随机数生成器。

因此,如果要shuffle()使用种子数字序列,则需要使用srand()而不是mt_srand().

在大多数其他情况下,您应该使用mt_rand()而不是rand(),因为它是一个更好的随机数生成器。

  • 嗯,使用 srand(123) 然后使用 rand() 似乎并不总是在 php 5.2.17 上产生相同的输出...... (2认同)