用种子随机化 PHP 数组?
我正在寻找一个可以在 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);
但它似乎不起作用。关于最好的方法有什么想法吗?
这个问题围绕着这个问题,但它已经很老了,没有人提供关于如何做到这一点的实际答案: Can i randomize an array byproviding a Seed并得到相同的订单? - “是” - 但如何呢?
更新
到目前为止的答案适用于 PHP 5.1 和 5.3,但不适用于 5.2。碰巧我想运行它的机器正在使用 5.2。
任何人都可以举一个不使用 mt_rand 的例子吗?它在 php 5.2 中被“破坏”,因为它不会根据相同的种子给出相同的随机数序列。请参阅 php mt_rand 页面 和 错误跟踪器 了解此问题。
I'm looking for a function that I can pass an array and a seed to in PHP and get back a "randomized" array. If I passed the same array and same seed again, I would get the same output.
I've tried this code
//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);
But it does not seem to work. Any thoughts on the best way to do this?
This question dances around the issue but it's old and nobody has provided an actual answer on how to do it: Can i randomize an array by providing a seed and get the same order? - "Yes" - but how?
Update
The answers so far work with PHP 5.1 and 5.3, but not 5.2. Just so happens the machine I want to run this on is using 5.2.
Can anyone give an example without using mt_rand? It is "broken" in php 5.2 because it will not give the same sequence of random numbers based off the same seed. See the php mt_rand page and the bug tracker to learn about this issue.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(12)
通常,您不应该尝试提出自己的算法来随机化事物,因为它们很可能存在偏见。 Fisher-Yates 算法 被认为既高效又公正:
示例(PHP 5.5.9):
Normally, you shouldn't try to come up with your own algorithms to randomize things since they are very likely to be biased. The Fisher-Yates algorithm is known to be both efficient and unbiased though:
Example (PHP 5.5.9):
您可以使用
array_multisort
按第二个数组mt_rand
值:这里
$order
是mt_rand< 的数组/code> 相同的值长度为
$arr
。array_multisort
对$order
的值进行排序,并根据$order
的值的顺序对$arr
的元素进行排序代码>.You can use
array_multisort
to order the array values by a second array ofmt_rand
values:Here
$order
is an array ofmt_rand
values of the same length as$arr
.array_multisort
sorts the values of$order
and orders the elements of$arr
according to the order of the values of$order
.您遇到的问题是 PHP 附带了两个内置的随机数生成器。
shuffle()
命令不使用mt_rand()
随机数生成器;它使用较旧的rand()
随机数生成器。因此,如果您希望
shuffle()
使用种子数字序列,则需要使用srand()
而不是mt_srand()< /代码>。
在大多数其他情况下,您应该使用
mt_rand()
而不是rand()
,因为它是更好的随机数生成器。The problem you have is that PHP comes with two random number generators built in.
The
shuffle()
command does not use themt_rand()
random number generator; it uses the olderrand()
random number generator.Therefore, if you want
shuffle()
to use a seeded number sequence, you need to seed the older randomiser, usingsrand()
rather thanmt_srand()
.In most other cases, you should use
mt_rand()
rather thanrand()
, since it is a better random number generator.主要问题涉及两个部分。一是关于如何洗牌。另一个是关于如何为其添加随机性。
一个简单的解决方案
这可能是主要问题的最简单的答案。对于 PHP 脚本编写中的大多数情况来说这已经足够了。但并非全部(见下文)。
上述方法可以做到,即使它不会为所有可能的种子数组组合产生真正的随机洗牌。然而,如果你真的希望它是平衡的,我想 PHP 不应该是你的选择。
对于高级程序员来说更有用的解决方案
正如 André Laszlo 所说,随机化是一件棘手的事情。通常最好让一个专用的对象来处理它。我的观点是,在编写 shuffle 函数时,您不需要担心随机性。根据您希望随机播放的随机程度,您可能有许多 PseudoRandom 对象可供选择。因此,上面的内容可能如下所示:
现在,这个解决方案是我要投票支持的解决方案。它将洗牌代码与随机化代码分开。根据您需要的随机类型,您可以对 PseudoRandom 进行子类化,添加所需的方法和您喜欢的公式。
并且,由于相同的洗牌函数可以与多种随机算法一起使用,因此一种随机算法可以在不同的地方使用。
The main question involves two parts. One is about how to shuffle. The other is about how to add randomness to it.
A simple solution
This is probably the simplest answer to the main question. It is sufficient for most cases in PHP scripting. But not all (see below).
The above method will do, even though it doesn't produce true random shuffles for all possible seed-array combinations. However, if you really want it to be balanced and all, I guess PHP shuldn't be your choice.
A more useful solution for advanced programmers
As stated by André Laszlo, randomization is a tricky business. It is usually best to let a dedicated object handle it. My point is, that you shouldn't need to bother with the randomness when you write the shuffle function. Depending on what degree of ramdomness you would like in your shuffle, you may have a number of PseudoRandom objects to choose from. Thus the above could look like this:
Now, this solution is the one I would vote for. It separates shuffle codes from randomization codes. Depending on what kind of random you need you can subclass PseudoRandom, add the needed methods and your preferred formulas.
And, as the same shuffle function may be used with many random algorithms, one random algorithm may be used in different places.
在最近的 PHP 版本中,植入 PHP 内置
rand()
和mt_rand()
函数不会每次都给出相同的结果。我不清楚这样做的原因(如果每次结果都不同,为什么你要为该函数提供种子。)无论如何,似乎唯一的解决方案是 编写您自己的随机函数用法:
上面的代码每次运行时都会输出以下序列:
只需更改种子即可获得完全不同的“随机数” 顺序
In recent PHP versions, seeding the PHP builtin
rand()
andmt_rand()
functions will not give you the same results everytime. The reason for this is not clear to me (why would you want to seed the function anyway if the result is different every time.) Anyway, it seems like the only solution is to write your own random functionUsage:
The code above will output the folowing sequence every time you run it:
Just change the seed to get a completely different "random" sequence
该变体也适用于 PHP 7.2 版本,因为 php 函数 create_function 在最新的 php 版本中已被弃用。
A variant that also works with PHP version 7.2, because the php function create_function is deprecated in the newest php version.
我想这可以完成工作:
为了不限制结果数组,将 $number_of_items_wanted 设置为 -1
为了不使用种子,请将 $seed 设置为 FALSE
I guess this will do the job :
In order to not limit the resulting array, set $number_of_items_wanted to -1
In order to not use a seed, set $seed to FALSE
在保持关键索引的同时进行种子洗牌:
Seeded shuffle while maintaining the key index:
一个简单的解决方案:
它可能不像 Fisher Yates shuffle,但我发现它给了我足够多的熵来满足我的需要。
A simple solution:
It might not be quite as random as the Fisher Yates shuffle, but I found it gave me more than enough entropy for what I needed it for.
根据@Gumbo、@Spudley、@AndreyP 的回答,它的工作原理如下:
Based on @Gumbo, @Spudley, @AndreyP answers, it works like that:
自制函数,使用crc32(注意:也返回负值(https ://www.php.net/manual/en/function.crc32.php))
Home Made function, using crc32(note:also returns negative value(https://www.php.net/manual/en/function.crc32.php))
这对我来说似乎是最简单的......
This seems the easiest for me...