srand

(PHP 4, PHP 5, PHP 7, PHP 8)

srand播种随机数生成器

描述

srand(?int $seed = null, int $mode = MT_RAND_MT19937): void

seed 播种随机数生成器,如果 seed0,则使用随机值。

注意: 不需要使用 srand()mt_srand() 播种随机数生成器,因为这是自动完成的。

警告

因为 Mt19937(“梅森旋转器”)引擎只接受一个 32 位整数作为种子,所以即使 Mt19937 的周期为 219937-1,可能的随机序列数量也仅限于 232(即 4,294,967,296)。

当依赖于隐式或显式随机播种时,重复项会更早出现。根据生日问题,在随机生成不到 80,000 个种子后,重复种子出现的概率为 50%。随机生成大约 30,000 个种子后,重复种子的概率为 10%。

这使得 Mt19937 不适合重复序列出现的概率不能超过微不足道的应用程序。如果需要可重复播种,Random\Engine\Xoshiro256StarStarRandom\Engine\PcgOneseq128XslRr64 引擎都支持更大的种子,这些种子不太可能随机碰撞。如果不需要可重复性,Random\Engine\Secure 引擎提供密码学安全的随机性。

注意: 从 PHP 7.1.0 开始,srand() 已成为 mt_srand() 的别名。

参数

seed

用线性同余生成器生成的数值填充状态,该生成器用解释为无符号 32 位整数的 seed 播种。

如果省略 seed 或为 null,将使用随机的无符号 32 位整数。

返回值

不返回值。

变更日志

版本 描述
8.3.0 seed 现在可以为空。
7.1.0 srand() 已成为 mt_srand() 的别名。

参见

添加注释

用户贡献的注释 13 个注释

harmen at no dot spam dot rdzl dot nl
15 年前
为了生成每天都不同的随机数,我使用了 Unix 纪元后的天数作为种子

<?php
srand
(floor(time() / (60*60*24)));
echo
rand() % 100;
?>

我的提供商最近升级了 php 服务器,调用 srand(seed) 似乎不再设置种子。为了让 srand 设置种子,请将以下行添加到您的 .htaccess 文件中

php_value suhosin.srand.ignore 0

感谢 doc_z (http://www.webmasterworld.com/php/3777515.htm)

Harmen
Niels Keurentjes
13 年前
请记住,许多 PHP 安装(如 Debian 和 DirectAdmin)默认安装的 Suhosin 补丁完全禁用了 srand 和 mt_srand 函数,以确保加密安全。为了从固定种子在 Suhosin 加固的服务器上生成可重复的随机数,您需要包含自己的伪随机数生成器代码。
rjones at ditzed dot org
23 年前
使用 srand() 种子 "(double)microtime()*1000000",如 [email protected] 在这些用户注释的开头提到的。

使用任何其他种子的最显著影响是,您的随机数往往在每次调用脚本时遵循相同或非常相似的序列。

注意以下脚本

<?php
srand
($val);

echo
rand(0, 20) . ", ";
echo
rand(0, 20) . ", ";
echo
rand(0, 20) . ", ";
echo
rand(0, 20) . ", ";
echo
rand(0, 20);
?>

如果您用一个常数播种生成器,比如数字 5($val = 5),那么生成的序列总是相同的,在这种情况下是(0, 18, 7, 15, 17)(至少对我来说是这样,不同的处理器/处理器速度/操作系统/操作系统版本/PHP 版本/Web 服务器软件可能会生成不同的序列)。

如果您用 time() 播种生成器,那么序列会更加随机,但非常接近的调用会具有相似的输出。

正如 [email protected] 在上面建议的那样,最好的种子是 (double) microtime() * 1000000,因为它提供了最大的伪随机性。事实上,它足以满足大多数用户的需求。
在一个从 1 到 20 生成 100000 个随机数的测试程序中,结果相当平衡,每个数字的平均结果约为 5000 个,偏差在 100 个左右。每次调用的偏差各不相同。
edublancoa at gmail dot com
19 年前
srand 的另一个用途是在确定的时间间隔内获得相同的 rand 值。例如:您有一个包含 100 个元素的数组,您需要每天获取一个随机项目,但不要在 24 小时内更改(想象一下“今天的照片”或类似的东西)。
<?php
$seed
= floor(time()/86400);
srand($seed);
$item = $examplearray[rand(0,99)];
?>
在您加载页面的 24 小时内,您每次都会获得相同的值。
contact at einenlum dot com
7 个月前
请记住,现在 srand 是 mt_srand 的别名,但它们在以前的行为不同。这意味着在使用 srand 时,您不应遵循 srand 的文档,而应遵循 mt_srand 的文档。

要将种子重置为随机值,`mt_srand(0)`(或 `srand(0)`)不起作用。它将种子设置为 0。要将种子重置为随机值,您必须使用 `mt_srand()`(或 `srand()`)。

<?php

$arr
= [0, 1, 2, 3, 4];

srand(1); // 或者使用 mt_srand(1),因为它们现在是别名
$keys = array_rand($arr, 2); // 与预期不同,不是随机的

srand(0); // 或者使用 mt_srand(0),因为它们现在是别名
$keys = array_rand($arr, 2); // 也不是随机的!

srand(); // 或者使用 mt_srand(),因为它们现在是别名
$keys = array_rand($arr, 2); // 再次随机

?>
Glauco Lins
8 年前
srand 和 mt_srand 都是每个进程 ID 只初始化一次。

在第一次调用 "srand"、"mt_srand"、"rand"、"mt_rand"、"shuffle" 或任何其他类似随机函数之后,您不能重新设定随机算法的种子。

我遇到了一个问题,在派生进程后,所有子进程都生成完全相同的随机值。
这是由于父进程第一次调用了 "shuffle",因此我无法重新设定子进程的种子。

为了解决我的问题,我简单地调用了 N 次 "rand",以偏移子进程的随机生成器。

# 偏移子进程随机生成器,以其 PID 为偏移量
$n = (getmypid() % 100) * (10 * abs(microtime(true) - time()));
for ($n; $n > 0; $n--) {
rand(0, $n);
}

由于每个 pcntl_fork 完成都需要一段时间,因此 microtime 提供了额外的偏移量,而不是仅增加一个 PID。

这段小程序在最坏情况下会执行 1000 次迭代。
mlwmohawk at mohawksoft dot com
22 年前
srand() 很难使用。您不应该在每个 PHP 进程中对随机数生成器播种超过一次,如果您这样做,您的随机性将限于您的种子的来源。

microtime 函数的微秒部分的分辨率非常有限,这就是在文档中添加 make_seed 函数的原因。您永远不应该两次获得相同的种子。

在较晚的 CVS 版本中,PHP 在执行 rand() 之前会对随机生成器播种,如果之前没有调用 srand()。
Anonymous
23 年前
我有一个随机循环器,它每天更改一段文本,我使用以下代码来确保种子足够独特。

$tm = time();
$today = mktime(0, 0, 0, (int)date("n", $tm), (int)date("j", $tm), (int)date("Y", $tm));
srand($today / pi());

pi 在整个过程中效果很好,它像一个魅力一样工作。任何其他大十进制数都可以,但 pi 是最常见的 "大" 数。
rjones at ditzed dot org
23 年前
作为对 srand() 用法的一个附注

如果您正在使用模块化编程,最好尝试从父脚本而不是从您可能正在使用的任何模块(使用 REQUIRE 或 INCLUDE)中调用 srand 例程。
这样,您可以避免从不同的模块中多次调用 srand() 的可能性。

当然,这种解决方案的缺陷在于,当使用另一个程序员编写的模块,或者为另一个程序员编写模块时。
您不能依赖另一个程序员在调用模块化函数之前调用 srand 函数,因此在这种情况下,您必须在模块内部包含 srand 函数。

如果您为其他程序员使用而编写模块,那么最好记录您已经调用了 srand 函数的事实。
或者,如果您使用的是另一个程序员编写的模块化函数,请检查其文档或检查其源代码。
MakeMoolah at themail dot com
23 年前
抱歉... 好吧,忘记上面 ^ 我说的话的一半吧。

证明我的例子的代码如下

<?php
srand
(5);
echo(
rand(1, 10));
srand(5);
echo(
rand(1, 10));
srand(5);
echo(
rand(1, 10));
?>

每次您都应该获得相同的答案,但是如果您这样做了

<?php
srand
(5);
echo(
rand(1, 10));
echo(
rand(1, 10));
echo(
rand(1, 10));
?>

那么答案将不同,并且您将让随机数公式发挥作用。
hagen at von-eitzen dot de
23 年前
确保 srand 只被调用一次 REALLY 很重要。
如果调用隐藏在您包含的第三方代码中的某个地方,这有点困难。例如,我使用了一个标准的横幅脚本,它*似乎*工作良好,在一个框架中放置了
三个随机横幅。但从长远来看,选择似乎
有些偏差 - 可能因为 srand 每次横幅调用一次,而不是
每次运行调用一次。
如果随机数生成器像在 PERL 中一样工作就好了:如果您使用随机函数,而之前从未在脚本中调用过 srand,
srand 会在之前被调用(并自动使用一个不错的种子,希望如此)。
我建议您应该做类似这样的事情

<?php
if (!$GLOBALS["IHaveCalledSrandBefore"]++) {
srand((double) microtime() * 1000000);
}
?>

(根据具体情况,您也可以使用静态变量)
bootc at bootc dot net
19 年前
好的,总结一下人们到目前为止所说的话

1. 如果可以,不要对 RNG 播种超过一次!
2. 如果您使用的是 PHP < 4.2.0,您必须自己对 RNG 播种。
3. 使用素数乘数对 microtime() 进行处理可能作用很小。使用 Mersenne Twister 替代。
4. 您可以使用 Mersenne Twister PRNG 与 mt_rand 和 mt_srand 函数。它更快,并且更随机。
akukula at min dot pl
23 年前
调用 srand((double)microtime()*1000000),
然后 $a=rand(1000000,9999999),然后 srand((double)microtime()*$a)
不会增加任何熵:rand 和 srand 的执行时间是
恒定的,因此第二个 microtime() 不会产生真正令人惊叹的东西。您可以安全地只使用第一个 srand()。
To Top