问题
Consider this method:
private static int GenerateRandomNumber(int seed, int max)
{
return new Random(seed).Next(max);
}
On my machine, executing this loop yields the same number through 1500 iterations:
for (int i = 0; i < 1501; i++)
{
int random = GenerateRandomNumber(100000000, 999999999);
Console.WriteLine(random.ToString());
Console.ReadKey();
}
I get 145156561, for every single iteration.
I don\'t have a pressing issue, I was just curious about this behavior because .Next(max) says \"Returns a Non Negative random number less than the specified maximum. Perhaps I am not understanding something basic.
回答1:
You're always seeding a new instance with the same seed, and then grabbing the first max. By using a Seed, you're guaranteeing the same results.
If you want to have a static, random number generation that does different results, you should rework this a bit. However, since Random is not threadsafe, it requires some synchronization when used statically. Something like:
private static Random random;
private static object syncObj = new object();
private static void InitRandomNumber(int seed)
{
random = new Random(seed);
}
private static int GenerateRandomNumber(int max)
{
lock(syncObj)
{
if (random == null)
random = new Random(); // Or exception...
return random.Next(max);
}
}
回答2:
Dilbert has encountered the same problem back in 2001:
http://dilbert.com/strips/comic/2001-10-25/
Coincidence?
I don't think so.
And random.org agrees : http://www.random.org/analysis/
回答3:
The problem is that you are creating a new Random instance with the same seed number each time. You should create a single Random instance (store it in a static if necessary) and simply call the next method on that same instance.
Random number generation is not truly random, see this Wikipedia entry for more details.
回答4:
Pseudo-random number generator usually work by choosing a seed, and then generating a deterministic sequence based on that seed. Choosing the same seed every time, you generate the same sequence.
There are "only" 2^32 different random sequences in .NET.
回答5:
Not sure how the internals work.. check wiki for it, but it's very simple.
public class MathCalculations
{
private Random rnd = new Random();
public Int32 getRandom(Int32 iMin, Int32 iMax)
{
return rnd.Next(iMin, iMax);
}
}
public class Main
{
MathCalculations mathCalculations = new MathCalculations();
for (int i = 0; i < 6; i++)
{
getRandom(0,1000);
}
}
will generate Number1, Number2, Number3, Number4, Number5, Number6 (1 seed, 1 sequence of many numbers, random*not really, but approx.*)
if you however do this:
public class MathCalculations
{
public Int32 getRandom(Int32 iMin, Int32 iMax)
{
Random rnd = new Random();
return rnd.Next(iMin, iMax);
}
}
public class Main
{
MathCalculations mathCalculations = new MathCalculations();
for (int i = 0; i < 6; i++)
{
getRandom(0,1000);
}
}
You will now get Number1, Number1, Number1, Number1, Number1, Number1 (1 seed, 6 equal sequences of many numbers, always pick the same starting number from each equal sequence).. At some point Number1 will be different, because the seed changes over time.. but you need to wait some time for this, nonetheless, you never pick number2 from the sequence.
The reason is, each time you generate a new sequence with the same seed, hence the sequence is the same over and over again, and each time your random generated will pick the first number in it's sequence, which, with the same seed, is of course always the same.
Not sure if this is technically correct by the underlying methods of the random generator, but that's how it behaves.
回答6:
In the event that anyone is looking for a "quick and dirty" "solution" (and I use that term with caution) then this will suffice for most.
int secondsSinceMidnight = Convert.ToInt32(DateTime.Now.Subtract(DateTime.Today).TotalSeconds);
Random rand = new Random(secondsSinceMidnight);
var usuallyRandomId = rand.Next();
Please note my use of usually random. I agree that the item marked as the answer is a more correct way of doing this.
回答7:
Salam to All, Well it drove me crazy as well. The answer is simple. Change the seed before you generate random.
Example: I want to generate random number between 1 to 10
Random rnd = new Random(DateTime.Now.Seconds);
int random_number = rnd.Next(10);
Put it inside a loop and run it three times. It will give out random numbers below 10.
来源:https://stackoverflow.com/questions/5264412/why-does-random-next-always-return-the-same-number