开发者

c++ generate a good random seed for psudo random number generators

I am trying to generate a good random seed for a psudo-random number generator. I thought I'd get the expert's opinions. let me know if this is a bad way of doing it or if there are much better ways.

#include <iostream>
#include <cstdlib>
#include <fstream>
#include <ctime>

unsigned int good_seed()
{
    unsigned int random_seed, random_seed_a, random_seed_b; 
    std::ifstream file ("/dev/random", std::ios::binary);
    if (file.is_open())
    {
        cha开发者_运维技巧r * memblock;
        int size = sizeof(int);
        memblock = new char [size];
        file.read (memblock, size);
        file.close();
        random_seed_a = int(memblock);
        delete[] memblock;
    }// end if
    else
    {
        random_seed_a = 0;
    }
    random_seed_b = std::time(0);
    random_seed = random_seed_a xor random_seed_b;
    return random_seed;
} // end good_seed()


The code that reads from /dev/random seems wrong: you're C-style casting the address of your character buffer into random_seed_a (plug for C++ casts here) and ignoring anything you actually read from /dev/random (try *reinterpret_cast<int*>(memblock).

/dev/random should already be a good entropy source, so if it's available don't possibly taint the value with any other data and just use it as the seed directly. If there isn't enough data in /dev/random I would just fall back on the time and use that by itself rather than xor'ing it with something.


Good pseudo-random number generators don't need a "good" seed, any seed (that's different from run to run) works equally well.

Using system time directly is fine (and common). Using /dev/random is also fine.

If your pseudo-random number generator isn't good, even picking a "good" seed won't help. Replace it if you can.

Suggestions: Mersenne twister is a pretty well regarded. Here's a precursor which will run on even the most limited of systems.


Ok here's the changes I made after considering your input. Thanks for everything by the way!

unsigned int good_seed()
{
    unsigned int random_seed, random_seed_a, random_seed_b; 
    std::ifstream file ("/dev/urandom", std::ios::binary);
    if (file.is_open())
    {
        char * memblock;
        int size = sizeof(int);
        memblock = new char [size];
        file.read (memblock, size);
        file.close();
        random_seed_a = *reinterpret_cast<int*>(memblock);
        delete[] memblock;
    }// end if
    else
    {
        random_seed_a = 0;
    }
    random_seed_b = std::time(0);
    random_seed = random_seed_a xor random_seed_b;
    std::cout << "random_seed_a = " << random_seed_a << std::endl;
    std::cout << "random_seed_b = " << random_seed_b << std::endl;
    std::cout << " random_seed =  " << random_seed << std::endl;
    return random_seed;
} // end good_seed()


Traditionally, we've used first or second user input to seed our values as the (tics to millisecond range) amount of time it takes them to respond is pretty variable.


Maybe you should prefer /dev/urandom/ over /dev/random. The latter blocks on Linux if there is not enough entropy available, which can easily happen if the program runs on a machine without user interaction. In case you cannot open /dev/urandom, you could throw an exception instead of using a fallback.


"Good" generators, "Bad generators" it doesn't mean anything. "Anyone who considers arithmetical methods of producing random digits is, of course, in a state of sin." - John von Neumann. Every such generator is just a deterministic algorithm. It's very important to have initial states ( seed ) that bring enough entropy. Depending on what you need, you should test your generator quality. Monte Carlo method is a very good estimator of a pseudo random number generator.


Define good. :-)

Is it important to find a seed quickly, or that the seed be as random as possible no matter how long it takes to put together?

For a balance - definitely not the most random, definitely not the fastest...

  • When it's first called, take the system time, in milliseconds.
  • Run that through a hash function, like SHA-1.
  • Use the result as the seed.

That should give you a mostly-random 160 bits, which is 10^50th or so of variability. The hash will take a split second to run, so this isn't lightning fast, but has been a good balance in the past for me.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜