保存/恢复PHP的rand状态()

问题描述:

为了防止长时间运行的预渲染脚本中的内存损坏,我希望能够对我的程序说“好吧,呈现前1000步”。然后我可以看看输出,检查它等。然后我想说“现在生成步骤1,001到10,000”。保存/恢复PHP的rand状态()

我的工作几乎完美。只有一件事我正在努力。

渲染脚本使用rand()向生成的输出添加熵,srand()在开始时确保它在重新渲染中保持不变。目前我通过计算调用次数rand()来“解决”这个问题,然后在开始实际生成之前多次调用它。问题在于它可能非常缓慢,尤其是当我生成了几百万个随机数时。

是否有任何方法可以确定我需要传递给srand()以继续生成序列的值?这甚至有可能吗?

如果没有,是否有任何方法可以找出确切的算法rand()正在使用?我真的很喜欢我从srand(43)得到的地图,并希望尽可能保留它!


编辑:使用Patashu的答案,这是我想出来的:

function rnd() { 
    static $seed = 42; 
    $seed = $seed*214013+2531011; 
    $mod = pow(2,32); 
    while($seed > $mod) $seed -= $mod; 
    $rs = floor($seed/65536)&0x7fff; 
    return floor(2*$rs/0x8000); 
} 

它依赖于使用花车因为据我可以告诉尾数的51位足够容易以完美的精度存储数字,如果使用位操作符,则整数会被截断或环绕。

+2

实际'rand'的实现取决于底层操作系统。这个事实可以有[令人惊讶的效果](http://cod.ifies.com/2008/05/php-rand01-on-windows-openssl-rand-on.html)。 – Gumbo 2013-02-25 04:22:23

这里http://cod.ifies.com/2008/05/php-rand01-on-windows-openssl-rand-on.html本页说明

被警告了PHP的兰特()的源代码,这是不是很漂亮,它是依赖于PHP的怪癖和兰特的OS()实现:)

+0

非常有用的链接,因为它似乎我可以再现这里使用的实际RNG。编辑我的问题以显示我正在使用的代码,它看起来是否适合您? – 2013-02-25 05:06:53

这不是直接回答你的问题,但因为它看起来像你不需要特别“好”随机数,为什么不看看写自己的伪随机数发生器?这样,您可以随时轻松地序列化和反序列化其状态。

http://en.wikipedia.org/wiki/Random_number_generation#Computational_methods算法的东西,甚至可能会做的伎俩。无论何时开始新的序列,您都可以使用当前时间播种。

+0

这可能是我最好的选择。我会失去我喜欢的地图,但我相信我会找到另一张地图。毕竟只有40亿种子可供选择:p – 2013-02-25 04:23:54

+0

因此,如果我理解正确,我可以使用类似的东西? 'function rnd(){static $ seed = 42; $ seed =(($ seed * 0x43fd43fd + 0xc39ec3)>> 4)&0xffffff;返回$ seed%2;}'得到一个随机的布尔值? – 2013-02-25 04:49:21

+0

@Kolink当然,对我来说很好。它可能不是*非常“随意”的,但它不应该比PHP所做的更糟,并且应该适合您的需求。你也可以尝试一下,看看你得到了什么样的发行。如果你想要更好的东西,你可以尝试实现http://en.wikipedia.org/wiki/Mersenne_twister – 2013-02-25 04:55:25