Php 生成可预测的泛光随机数组

Php 生成可预测的泛光随机数组,php,arrays,algorithm,random,Php,Arrays,Algorithm,Random,所以 问题 这是众所周知的“Pseudo”实际上意味着,尽管它们通常是随机的(即不可预测的),但它们在序列上仍然是相同的,在序列中使用了相同的生成器初始值。例如,在PHP中有这样一个函数。例如: mt_srand(1); var_dump(mt_rand(), mt_rand(), mt_rand()); -不管我们启动脚本多少次:生成的三个数字在顺序上总是相同的 现在,我的问题是如何做同样的-但洗牌数组。也就是说,我想创建一个函数,它将接受输入数组进行洗牌和种子。在同一种子值内,洗牌必须具有

所以

问题

这是众所周知的“Pseudo”实际上意味着,尽管它们通常是随机的(即不可预测的),但它们在序列上仍然是相同的,在序列中使用了相同的生成器初始值。例如,在PHP中有这样一个函数。例如:

mt_srand(1);
var_dump(mt_rand(), mt_rand(), mt_rand());
-不管我们启动脚本多少次:生成的三个数字在顺序上总是相同的

现在,我的问题是如何做同样的-但洗牌数组。也就是说,我想创建一个函数,它将接受输入数组进行洗牌和种子。在同一种子值内,洗牌必须具有连续的相同顺序。也就是说,让我们调用该函数
shuffleWithSeed()
——然后在每次脚本启动时都应该使用以下函数:

$input = ['foo', 'bar', 'baz'];
$test  = shuffleWithSeed($input, 1000);//1000 is just some constant value
var_dump($test); //let it be ['bar', 'foo', 'baz']
$test  = shuffleWithSeed($test, 1000); 
var_dump($test); //let it be ['baz', 'foo', 'bar']
$test  = shuffleWithSeed($test, 1000); 
var_dump($test); //let it be ['baz', 'bar', 'foo']
//...
-i、 e.无论我们对数组执行多少次洗牌-我希望下一次脚本启动的顺序在一个
种子
值内始终相同

我的方法

我想到了这个算法:

  • 使用传递的
    种子初始化随机数生成器
  • 生成
    N
    随机数,其中
    N
    $input
    成员数
  • 对步骤2中的数字进行排序
  • 使相应的数字依赖于
    $input
  • 我已在以下方面实施了此功能:

    function shuffleWithSeed(array $input, $seed=null)
    {
       if(!isset($seed))
       {
          shuffle($input);
          return $input;
       }
       if(!is_int($seed))
       {
          throw new InvalidArgumentException('Invalid seed value');
       }
       mt_srand($seed);
       $random = [];
       foreach($input as $key=>$value)
       {
          $random[$key] = mt_rand();
       }
       asort($random);
       $random = array_combine(array_keys($random), array_values($input));
       ksort($random);
       return $random;
    }
    
    -现在,我们也找到了算法——但不确定它是否能处理伪随机数(即种子)

    问题

    如您所见,我在函数中进行了两种排序—第一种是按值排序,第二种是按键排序

    • 这可以用一种方法完成吗?还是完全没有排序?输入数组可能很大,所以我想避免这种情况
    • 但是,可能是我的算法不好吗?如果是,可以建议哪些其他选择

      • 这是我不久前为实现此目的而实现的一个函数的复制和粘贴:

        /**
         * Shuffles an array in a repeatable manner, if the same $seed is provided.
         * 
         * @param array &$items The array to be shuffled.
         * @param integer $seed The result of the shuffle will be the same for the same input ($items and $seed). If not given, uses the current time as seed.
         * @return void
         */
        protected function seeded_shuffle(array &$items, $seed = false) {
            $items = array_values($items);
            mt_srand($seed ? $seed : time());
            for ($i = count($items) - 1; $i > 0; $i--) {
                $j = mt_rand(0, $i);
                list($items[$i], $items[$j]) = array($items[$j], $items[$i]);
            }
        }
        

        它使用种子随机数生成器实现了一个简单的函数。

        Wow,我找到了Fisher Yates,并且正在键入我对将其用于伪随机数的犹豫。你的样本表明我的想法是正确的。谢谢,现在我完全明白了。有没有办法重新排列$items以获得通过的$items的原始顺序?@nils什么?只是复制一个你不需要洗牌的副本@零啊,我明白了。我不知道。会成为一个有趣的新问题。但对于@nils来说,可能更多的东西是:是的,它非常简单: