【问题标题】:PHP: are rand() pseudo generated numbers always the same for a given seed supplied?PHP:对于提供的给定种子,rand() 伪生成的数字是否总是相同的?
【发布时间】:2015-12-05 14:50:12
【问题描述】:

我正在使用此代码生成一系列伪随机数:

$seed = 1;
srand( $seed );
for($i=0; $i<10; $i++)
{
    echo rand(0,100) . "\n";
}
exit(0);

以下代码总是输出(在我的机器上)

84
39
79
[....]
77
28
55

我可以相信上述代码的输出总是相同的吗?

如果没有,什么可以改变它?

例如,不同版本的 PHP 会给出不同的结果吗?

还是 PHP 运行在不同的操作系统上?

【问题讨论】:

  • 不确定 32 位/64 位 PHP 是否会产生变化
  • @MarkBaker 好像不是这样:32bit64bit
  • 没有,自己测试了一下,32位和64位没有区别
  • 虽然我在 Windows 上运行它,但我得到的序列是 99、38、79、21、75、91、42、36、47、67....所以它可能是那是操作系统会有所不同。它与我的 Windows 机器上的所有版本(32 位或 64 位)一致,而如果我在 Linux 机器上运行它,我始终会得到与你的 3v4l 相同的数字序列

标签: php random number-sequence


【解决方案1】:

如果我在 Windows 上运行此代码,我会得到 99、38、79、21、75、91、42、36、47、67 的序列。它与所有版本一致,32 位或 64 位我的 Windows 盒子。

而如果我在 Linux 机器上运行它,无论 PHP 的哪个版本,我始终会得到 84、39、79、80、92、19、33、77、28、55 的序列

所以操作系统之间并不一致


但是,如果我使用 mt_srand()mt_rand() 而不是 srand()rand(),那么我确实可以在 Windows/Linux 和从 5.2 到 7.0 的不同版本的 PHP 之间获得一致性

$seed = 1;
mt_srand( $seed );
for($i=0; $i<10; $i++)
{
    echo mt_rand(0,100) . "\n";
}
exit(0);

始终给出 58、0、72、94、100、87、70、100、86、76

【讨论】:

  • 警告,如果内存服务正确,它甚至在不同的 php 版本之间都不一致。
  • 是的,5.2.1 - 7.0.0 的输出:580729410087701008676 4.3.0 - 5.2.0 的输出:89985189699593497888 -- 3v4l.org
  • 当然,如果有人仍在使用 PHP
  • 玩得开心下次PHP改变mt_rand方案,你的程序/数据库依赖于旧方案,你必须在用户态PHP中重写旧的mt_rand :)
  • @MarkBaker 接受的答案不正确,正如其他人所指出的那样。我有 23,25,37,100,100,95,72,14,49,84
【解决方案2】:

不保证随机数在操作系统或 PHP 版本之间是相同的。所以最好的办法是创建你自己的伪随机数生成器,正如blog post中所指出的@

代码如下:

<?php

class Random {

    // random seed
    private static $RSeed = 0;

    // set seed
    public static function seed($s = 0) {
        self::$RSeed = abs(intval($s)) % 9999999 + 1;
        self::num();
    }

    // generate random number
    public static function num($min = 0, $max = 9999999) {
        if (self::$RSeed == 0) self::seed(mt_rand());
        self::$RSeed = (self::$RSeed * 125) % 2796203;
        return self::$RSeed % ($max - $min + 1) + $min;
    }

}

// set seed
Random::seed(42);

// echo 10 numbers between 1 and 100
for ($i = 0; $i < 10; $i++) {
    echo Random::num(1, 100) . ',';
}
echo "\n";

for ($i = 0; $i < 10; $i++) {
    echo Random::num() . ',';
}
echo "\n";

结果:

76,86,14,79,73,2,87,43,62,7,
393758,1684299,822150,2105442,337168,202955,203548,277673,1154689,1729772,

显然,您将在不同的 PHP 版本之间获得一致的结果。请注意,您必须提供种子,否则此功能将退回到mt_rand,然后您将再次受制于操作系统!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-03-31
    • 2016-09-20
    • 2017-08-06
    • 2016-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多