【问题标题】:Is rand() time-dependent in php?rand() 在 php 中是否与时间相关?
【发布时间】:2012-06-26 08:49:46
【问题描述】:

让我们解释一下我的意思。

前段时间,在用c#编写程序时,我犯了以下错误:

int Randomize()
{
    Random r=new Random();
    return  r.Next(0,10);
}

在c#中,这是一个错误,因为连续调用多次,这个函数将返回相同的值。这是因为 Random 构造函数使用时间种子,并且调用之间的时间差太小(我花了一个小时才找到那个:))。

现在我在 php 中使用 rand(...),我需要输出始终不同,即使同时执行 2 个脚本。

我必须做些什么才能得到这个结果,还是它被设计成这样工作?

【问题讨论】:

  • 让它工作吧,虽然 mt_rand() 比 rand() 好
  • 好问题。我无法具体详细回答,但这些天公认的 PRNG 选择是 mt_rand,而不是 rand。
  • 好一个,但我认为在你的情况下很难确保输出不同,即使同时执行两个脚本
  • 我的理解是PHP使用了底层系统的rand()功能。您可以(尽管我不建议这样做)尝试使用客户端 IP 和当前时间的某种组合来播种 PRNG,但是有更好的 PRNG 实现,包括基于 mersenne twister 的实现mt_rand已经提到了

标签: php random


【解决方案1】:

关于mt_rand()函数...

来自http://php.net/manual/en/function.mt-srand.php

从 PHP 4.2.0 开始,无需使用 srand() 或 mt_srand() 为随机数生成器播种,因为现在这是自动完成的。

(对于 PHP 5.2.1)PHP 中的 Mersenne Twister 实现现在使用 Richard Wagner 的新种子算法。相同的种子不再产生与以前版本相同的值序列。这种行为预计不会再次改变,但仍然认为依赖它是不安全的。

这里是link,描述了“Mersenne Twister(MT)”伪随机数生成算法(以及 C、C++、C# 中的implementations)

Here 你可以在 PHP 5 中找到这个函数的实现

在php_rand.h 我发现了这个:

#ifdef PHP_WIN32
#define GENERATE_SEED() (((long) (time(0) * GetCurrentProcessId())) ^ ((long) (1000000.0 * php_combined_lcg(TSRMLS_C))))
#else
#define GENERATE_SEED() (((long) (time(0) * getpid())) ^ ((long) (1000000.0 * php_combined_lcg(TSRMLS_C))))
#endif

所以现在你可以看到,PHP 中的随机函数依赖于time 函数...

【讨论】:

  • 还可以查看lcg.c。如果尚未播种,则取决于时间一次。根据定义,lcg在每次调用后都会产生一个新的随机值,并且每次调用不依赖于时间函数。
【解决方案2】:

rand() 和 mt_rand() 调用 srand() 和 mt_srand() 总是产生随机结果。 但这里有一篇关于 php.net 的有趣帖子:

请注意,自动播种似乎是用当前的 秒数,这意味着您可以多次获得相同的结果 在快速服务器上运行。要么自己打电话给 srand() 经常更改种子或使用 mt_rand() 似乎没有 遇到问题。

所以,请更频繁地致电srand 或mt_rand。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2011-06-26
  • 2017-10-28
  • 1970-01-01
  • 2014-05-19
  • 1970-01-01
  • 2010-09-08
  • 2017-01-26
  • 1970-01-01
相关资源
最近更新 更多