可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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?
回答1:
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
回答2:
Pseudo-random number generators like Random
should only be seeded once, so:
private static Random _rand = new Random();
public static int Roll()
{
return _rand.Next(1, 100);
}
(Note I made the return value int
rather than void
; the Roll
function as quoted in the question results in a syntax error.)
But your title says "Creating a true random". Random
won't do that for you, it's a pseudo-random number generator, meaning it's deterministic, just hard to predict if you don't know the seed. Usually that's good enough for most purposes, but if you need real randomness, you need an entropy source. http://random.org is one popular one.
回答3:
You should create your Random class only once outside your Roll function and seed it with a unique value.
You are recreating your Random each time you call Roll which causes the 'not random numbers'.
回答4:
Should I use the RNGCryptoServiceProvider class to generate rolls instead?
If this is a serious game with money at stake then: Yes.
回答5:
I'm assuming that you are calling the Roll()
method so quickly that Now.Ticks
is the same?
The simplest way to get around this would be rather than to create a new Random()
instance each time you call Roll()
create a static variable to hold a single instance of Random()
.
回答6:
The usual way to use random number generators is to seed them once, save them and call on them repeatedly throughout your programme. As long as you seed from a suitable value at the start, you should get acceptable randomness - assuming the generator you're using is using a function returning things which are suitably random for your purposes. So, save your Random instance outside the Roll() function, seed it the first time it's used, then just call Next() on it each time you need another number.
When you get right down to it, there's no such thing as true random number generation on a computer, only pseudorandom sequences based on a seed. However, humans are terrible at identifying randomness, so it's usually okay.