in reply to Re^2: Getting srand's seed
in thread Getting srand's seed

There are a number of really important things that you haven't told us. The most important pertains to the specific build of Perl that you are using because that influences the number of bits that rand uses for its seed. For standard Windows builds of Perl 2**15 values are all there are!

I suggested $seed = int(rand(2**31)); because most current Perl builds handle 32 bit integers without trouble and that would encompass the majority of seed sizes you are likely to encounter with standard builds of Perl. It also has the large advantage over using something like $seed = time ^ ($$ + ($$ << 15)); that the full entropy used to generate the "system" seed is retained.

We can't tell what you really want unless you tell us the nature of your application. If all you are doing is generating mazes for net hack then there really isn't an issue.


Perl reduces RSI - it saves typing

Replies are listed 'Best First'.
Re^4: Getting srand's seed
by fangly (Initiate) on Oct 10, 2008 at 03:26 UTC
    My Perl is "perl v5.8.8 built for i486-linux-gnu-thread-multi". The application I am writing does not pertain to security or cryptography, it is for a scientific application. I'd rather keep it as portable as possible.

    I'm not overly worried about the quality of the stock Perl rand() or about exhausting the numbers of random numbers it can produce. I don't think I would need more than 100,000 numbers.

    I originally only wanted access to the seed, but not being able to do so using stock Perl has led me to deal with things I am not very familiar with like how to generate a seed, etc...

    What method would you recommend me to do? I'm unclear about some of the differences.

  • Just use the stock srand() with a home-made seed like you explained earlier
  • Or maybe using the Math::Random module. It seems nice because it has the option to create and report a seed. But is it a higher quality random number generator. Is it slower than the stock one?
  • Or maybe Math::Random::RT? It seems to be higher quality but is a bit slower. But would have to be seeded manually?

    Thanks for the help GrandFather!

      Pseduo random number sequence generators (which is what we are really talking about) are tricky things and are subject to much tricky maths that I don't understand. However there are various quality attributes that characterise such generators and default rand generators often exhibit among the worst results for those qualities.

      One simple quality is the number of bits used by the generator. Perl tends to use the rand provided by the runtime library of the C compiler used to build it. ActiveState's Perl build for example uses only 15 bits! You can find out how many bits you Perl build uses by:

      use Config; print $Config{randbits};

      In fact the seeding snippet I gave earlier could be rewritten using that information as $seed = int(rand(2**$Config{randbits} - 1)); (although that may produce odd results if $Config{randbits} == $Config{longsize} * 8). Note that 2**2**$Config{randbits} is generally the maximum cycle length for rand.

      Another area where rand is often poor is correlation between successive values. This may be a more important consideration where you are generating numbers for modelling or statistical applications. There is a pile of stuff on the internet about these sorts of applications and suitable generators. You could start at Pseudorandom_number_generator.

      For your application I strongly recommend that you use Math::Random::MT for your actual generator. It is a robust generator that is generally quick enough and has a very long cycle period. It is also very easy to use. Just put:

      use Math::Random::MT qw(srand rand);

      and you are in business - the MT generator replaces Perl's built in rand seamlessly.


      Perl reduces RSI - it saves typing
        I seem to have $Config{randbits} = 48 and  $Config{longsize} = 4. But using $seed = int(rand(2**$Config{randbits} - 1)); produced very poor results. Even when the seed was different, I would get the same series random numbers using my $pick = int(rand(1e9))+1;

        In any case, it's not important because I am now using Math::Random::MT, and its srand() function takes unsigned 32-bit integers. Thus I have to produce my seed between 0 and 2**32-1.

        It worked quite well, but I noticed that I would get the same seed when my program was called several times in a short time frame. So I had to seed the PRNG with a fast-moving seed first before I could produce my actual random seed.

        use Math::Random::MT qw(srand rand); I'm quite happy now with the result. I appreciate your advices GrandFather. The final code looks like this:
        use Math::Random::MT qw(srand rand); sub seed_prng { # Seed the pseudo random number generator with a random or specified + seed # Returns what seed value is used my ($seed) = shift; if (not defined $seed) { # Want to produce an random unsigned 32-bit integer to feed to # Math::Random::MT::srand(). That means, first seed srand() with a + temporary # seed that varies quickly in time so we don't get twice the same +seed if we # request several seeds in a short interval of time. my $tmp_seed = time ^ ($$ + ($$ << 15)); # shown in srand's doc srand($tmp_seed); my $max = int(2**32-1); # Largest unsigned 32-bit integer $seed = int(rand($max+1)); # An integer between 0 and $max } srand($seed); return $seed; }