开发者

regain constant pseudo-random in PHP 5.2

I am including the same "random.inc" in foo.php and bar.php. For each, I want reproducible "random" results.

So in foo.php I always want one set of numbers and/or keywords. In bar.php another. Which shouldn't change on reload. That's what I mean by contant pseudo-random. And that's why I seeding on the url. However I still get different results for individual numbers as well as for array pickson every reload. This is the full php file:

<?
    header('Content-Type: text/plain');
    $seed = crc32( $_SERVER['REQUEST_URI'] );
    echo "phpversion: ".phpversion()."\nseed: $seed\n";
    srand( $seed ); // (seed verified to be contant as expected)

    // neither single values nor array pics turn out deterministic
    echo ''.rand(0,开发者_运维问答100).' '.rand(0,100).' '.rand(0,100)."\n";
    $values = array( '0'=>21,'1'=>89,'2'=>96,'3'=>47,'4'=>88 );
    print_r( array_rand( $values, 3 ) );
?>

In the days of PHP4.1 it was (verified) possible to achieve constant pseudo-random like this. array_rand API documentation describes as a feature that since 4.2 initialization happens automatically. Perhaps this is overriding any explicit seeding? (if so, perhaps explicit seeding should raise an internal PHP flag, preventing automatic seeding?). Btw: mt_srand() and srand() are equally not working.

I would really like to get my deterministic / constant pseudo-random back...

Update: Solution below (Windows and/or version 5.2 's fault)


Works for me (PHP/5.3.6):

<?php

$data = range(1, 100);
srand(1);
print_r(array_rand($data, 3));

... always prints:

Array
(
    [0] => 21
    [1] => 89
    [2] => 95
)

... in my machine. Apparently, the exact numbers differ depending on the exact environment but they're reproducible.


Guys, you are all correct! (Sorry, I answer it myself now)

  • my web hoster runs 5.2.17 under Linux 2.6.36, and above problem exists.
  • under Win x64 5.3.0 everything works as expected.

So it's everyone's guess if that's an OS related bug and/or a PHP bug, fixed in 5.3.0.

Given that random constant seeding worked before, I am guessing they fixed in 5.3 the bug that came with the autoseed feature enhancement in 4.2. Anyway, Thanx again, at least there's clarity now.


The seeding functions are still available, and should still work; it's just since PHP 4.2 they are automatically seeded with the time on page load; but you can still call them to reset the random sequence to a known starting point.

[edit] I have just done a quick test program to make sure I wasn't imagining it!

mt_srand(50000);
print "rand="+mt_rand(0,10000);

Using PHP 5.2, this always results in the same value being printed (1749).

[EDIT] As noted by @cwd and in the accepted answer to this question, there appears to be a discrepancy in PHP 5.2's behaviour with random number seeding between the Linux and Windows versions. In PHP 5.2 on Linux, the above technique does not appear to work.

Fortunately, the bug seems to have been fixed in PHP 5.3, so the solution to this problem is simply to upgrade. (PHP 5.2 is not supported any longer, so you should upgrade anyway)


Btw, if anyone else wants "constant windows-pre-5.3 pseudo-random" (of low quality, e.g. for stuff like SEO buzzwording) this is a tested workaround:

$r = abs(crc32($URL))%20; // a number between 0 and 19, based on URL


In PHP 5.2.17 and probably on all versions of PHP 5.2, (not sure about windows), we lose the capability of generating random numbers based on a seed as PHP changes the algorithm used for random numbers.

rand and mt_rand are "broken" not only because they will not give one random number, but they will also not give a same sequence of random numbers - even when using a seed!

At first the PHP developers tried to argue that this is the way that it "should" work, but we can guess they caught enough grief about the problem that they have reverted the way that it works with PHP 5.3.

See the php mt_rand page and the bug tracker to learn about this issue.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜