Possible Duplicate:
Why does it appear that my random number generator isn't random in C#?
How can I generate truly (not pseudo) random numbers with C#?
I've created a dice game where the dice is based on a percentile, 1-100.
public static void Roll()
{
Random rand = new Random((int)DateTime.Now.Ticks);
return rand.Next(1, 100);
}
But I don't feel like it's a real random based on current time.
If I do
for (int i = 0; i < 5; i++)
{
Console.WriteLine("#" + i + " " + Roll());
}
They would all be the same values, because the DateTime.Now.Ticks
didn't change, it seeded the same number.
I was thinking I could generate a new random seed if the seed was the same due to the current time, but it doesn't feel like an honest "re-roll"
What should I do to try and replicate a close to real/honest dice roll? Should I use the RNGCryptoServiceProvider
class to generate rolls instead?
Computational random number generators can typically generate pseudorandom numbers much faster than physical generators, while physical generators can generate "true randomness."
There are two main methods that a computer generates a random number: true random number generators (TRNGs) and pseudo-random number generators (PRNGs). The former uses some phenomenon outside the computer for its number generation, whereas the latter relies on pre-set algorithms to emulate randomness².
A PRNG is much faster than a TRNG, hence it is common to generate a seed using a TRNG to initialize a PRNG. After that, the PRNG generates the random numbers. In the Linux kernel /dev/random uses an entropy pool to generate random data.
Randomness is relational. The problem modern computers have with randomness is that it doesn't make mathematical sense. You can't program a computer to produce true randomness—wherein no element has any consistent, rule-based relationship to any other element—because then it wouldn't be random.
DateTime.Now.Ticks
only has a resolution of approximately 16ms, so if you create a Random
with that overload multiple times within a 16ms "slot" they will all be seeded with the same value and therefore you will get the same sequence.
Initialize your Random
outside your loop so that a single Random
sequence is produced, rather than creating it each time within the loop which could result in Randoms
being seeded with the same value and so produce the same sequence.
Update
My previous point that the default constructor initialized Random
with CPU ticks was incorrect, the default constructor actually uses Environment.TickCount which is:
A 32-bit signed integer containing the amount of time in milliseconds that has passed since the last time the computer was started.
Which still has a low resolution. If you make multiple instances of Random
in quick succession, they can easily be created within the same time slot and therefore have the same seed value, and create the same sequence. Create a single instance of Random
and use that.
Update
Further to your comments, if you wish to generate a random sequence across multiple threads, please see the following Jon Skeet article which discusses a thread-safe wrapper:
https://codeblog.jonskeet.uk/2009/11/04/revisiting-randomness
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With