Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Save/restore the state of PHP's rand()

Tags:

php

random

In an attempt to prevent memory corruption in a long-running pre-rendering script, I want to be able to say to my program "okay, render the first 1,000 steps". Then I can take a look at the output, inspect it, etc. Then I want to say "now generate steps 1,001 through 10,000".

I have it working almost perfectly. There's just one thing I'm struggling with.

The rendering script uses rand() to add entropy to the generated output, with srand() at the start to ensure it remains constant in re-renders. Currently I "solve" this issue by counting how many times rand() is called, and then calling it that many times before starting the actual generation. The problem with this is that it can be very slow, especially when I've generated a few million random numbers.

Is there any way to determine what value I need to pass to srand() to continue generating the sequence? Is this even possible?

If not, is there any way to find out what exact algorithm rand() is using? I really like the map I'm getting from srand(43) and would like to keep it if possible!


EDIT: Using Patashu's answer, here's what I've come up with:

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);
}

It relies on the use of floats because as far as I can tell the 51 bits of the mantissa are easily enough to store the numbers with perfect precision, and integers get truncated or wrap around if bit operators are used.

like image 926
Niet the Dark Absol Avatar asked Oct 21 '22 16:10

Niet the Dark Absol


2 Answers

This does not directly answer your question, but since it looks like you don't need particularly "good" random numbers, why not look into writing your own pseudo-random-number generator? This way you can easily serialize and deserialize its state whenever you need.

Something like the algorithm at http://en.wikipedia.org/wiki/Random_number_generation#Computational_methods may even do the trick. You can seed it with the current time whenever you start a new sequence.

like image 120
lc. Avatar answered Oct 27 '22 10:10

lc.


This page here http://cod.ifies.com/2008/05/php-rand01-on-windows-openssl-rand-on.html explains the source code for PHP's rand()

Be warned, it's not very pretty and it's dependent on quirks of PHP and your OS implementation of rand() :)

like image 33
Patashu Avatar answered Oct 27 '22 09:10

Patashu