Seeding a pseudo-random number generator in C#
I need a seed for an instance of C#'s Random
class, and I read that most people use the current time's ticks counter for this. But that is a 64-bit value and the seed needs to be a 32-bit value. Now I thought that 开发者_StackOverflow社区the GetHashCode()
method, which returns an int
, should provide a reasonably distributed value for its object and this may be used to avoid using only the lower 32-bits of the tick count. However, I couldn't find anything about the GetHashCode() of the Int64
datatype.
So, I know that it will not matter much, but will the following work as good as I think (I can't trial-and-error randomness), or maybe it works the same as using (int)DateTime.Now.Ticks
as the seed? Or maybe it even works worse? Who can shed some light on this.
int seed = unchecked(DateTime.Now.Ticks.GetHashCode());
Random r = new Random(seed);
Edit: Why I need a seed and don't just let the Random()
constructor do the work? I need to send the seed to other clients which use the same seed for the same random sequence.
new Random()
already uses the current time. It is equivalent to new Random(Environment.TickCount)
.
But this is an implementation detail and might change in future versions of .net
I'd recommend using new Random() and only provide a fixed seed if you want to get a reproducible sequence of pseudo random values.
Since you need a known seed just use Environment.TickCount
just like MS does. And then transmit it to the other program instances as seed.
If you create multiple instances of Random
in a short interval (could be 16ms) they can be seeded to the same value, and thus create the same pseudo-random sequence. But that's most likely not a problem here. This common pitfall is caused by windows updating the current time(DateTime.Now
/.UtcNow
) and the TickCount(Environment.TickCount
) only every few milliseconds. The exact interval depends on the version of windows and on what other programs are running. Typical intervals where they don't change are 16ms or 1ms.
If you need to seed it with something other than the current time (in which case you can use the default constructor), you can use this:
Random random = new Random(Guid.NewGuid().GetHashCode());
I had a similar question , to select a random set of questions from a larger list of questions. But when I use the time as the seed it gives the same random number .
So here is my solution.
int TOTALQ = 7;
int NOOFQ = 5;
int[] selectedQuestion = new int[TOTALQ];
int[] askQuestion = new int[NOOFQ];
/* Genarae a random number 1 to TOTALQ
* - if that number in selectedQuestion array is not o
* - Fill askQuestion array with that number
* - remove that number from selectedQuestion
* - if not re-do that - - while - array is not full.
*/
for (int i = 0; i < TOTALQ; i++) // fill the array
selectedQuestion[i] = 1;
int question = 0;
int seed = 1;
while (question < NOOFQ)
{
DateTime now1 = new DateTime();
now1 = DateTime.Now;
Random rand = new Random(seed+now1.Millisecond);
int RandomQuestion = rand.Next(1, TOTALQ);
Response.Write("<br/> seed " + seed + " Random number " + RandomQuestion );
if (selectedQuestion[RandomQuestion] != 0)
{
selectedQuestion[RandomQuestion] = 0; // set that q =0 so not to select
askQuestion[question] = selectedQuestion[RandomQuestion];
Response.Write(". Question no " + question + " will be question " + RandomQuestion + " from list " );
question++;
}
seed++;
}
精彩评论