可重复的随机数序列

13

如何在PHP中获得一系列可重复的伪随机数?

在旧版本的PHP中,我只需在RNG中使用相同的种子即可实现,但是自从PHP更改了rand和mt_rand的工作方式后,这种方法不再适用。

请还参阅PHP.net页面上的此评论:

请注意,默认情况下安装了Suhosin补丁,例如Debian和DirectAdmin等许多PHP安装都会完全禁用srand和mt_srand函数以提高加密安全性。要在经过Suhosin硬化的服务器上从固定种子生成可重复的随机数,您需要包括自己的伪随机生成器代码。

该评论的链接:http://www.php.net/manual/en/function.srand.php#102636

有没有已经准备好的解决方案? 我没有时间也没有经验来创建自己的伪随机生成器代码。

我的目标是有一个代码。

<?php
   //( pseudo random code here...)
   $the_seed = 123; // 123 is just a number for demo purposes, NOT a static number
                    //...i hope you get the idea. It's just a hardcoded seed,
                    // it could be a seed based on a user-id, a date etc...
                    // we need the same output for a given seed.
   //( pseudo random code here...)

   // ...and finally
   echo $the_random_number;
 ?>

所以每次我访问这个页面,我应该得到相同的数字。


6
$the_random_number设置为9即可。 - CanSpice
1
你对随机的定义有误。 - Zirak
6
区别在于他不需要存储成百上千甚至上百万个数字 - 它们可以即时生成。他感兴趣的不仅是 PRNG 返回的第一个数字,而且希望能够获得许多数字,而无需将它们存储下来。 - Adam Davis
1
@Sharky:显然你没有理解我所说的笑话。 - CanSpice
2
@CanSpice 应该链接到xkcd漫画。 - Adam Davis
显示剩余5条评论
4个回答

11

谢谢您,先生。我现在就去尝试一下……我会尽快接受答案的 :) - Sharky
1
还想为PHP < 5.3.0添加此实现 http://boxrefuge.com/?p=18(刚发现并测试它的工作效果非常好 - 还有关于性能的有趣文章,一定要看看) - Sharky
为什么不使用内置的PHP随机函数? - McKay
2
@McKay,问题的第二段回答了你的问题。简而言之,他需要对于给定的输入获得相同的随机数序列 - 这通常通过每次使用相同的种子来初始化随机数生成器来实现。然而,PHP的一个常见安全补丁移除了初始化随机数生成器的能力,因为太多人将其用于密码学应用,但没有使用密码学安全的种子源。 - Adam Davis
boxrefuge.com 的实现不正确(与参考实现产生的结果不同) - cmcnulty

7

根据某些指标,最好的随机数算法之一是Mersenne Twister。您可以在此处找到一个纯PHP版本here(还有其他版本)。

然后您可以调用:

init_with_integer($integer_seed)

并且每次都能获得相同的输出(对于给定的种子)。


2
如果您不需要高质量的输出,Lehmer RNG 算法非常简单。它是其中一种算法,可能已被 srand() 在内部使用(取决于您的操作系统)。
$seed = 42; // any integer, maybe a database id

// init Lehmer RNG
$seed = $seed % 2147483647;
if ($seed <= 0) $seed += 2147483646;

// generate as many random numbers as you need
$seed = $seed * 48271 % 2147483647;
print($seed);

$seed = $seed * 48271 % 2147483647;
print($seed);

$seed = $seed * 48271 % 2147483647;
print($seed);

$seed = $seed * 48271 % 2147483647;
print($seed);
...

您可以使用以下方法将输出限制在特定范围内:
$min = 0;
$max = 9;
print($min + ($seed % $max));

1

这不是最好的,但它是一个可用的。

function ranseed($min, $max, $seed) {
    return round($min + (hexdec(md5($seed)) / hexdec("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")) * ($max - $min));
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接