开发者

C# Random codes - Is most of it simply wrong?

I had a lot of issues with randomizing lists. I am talking about a list of 200 elements, where I want to shuffle the list. Don't get me wrong, I read a lot of examples, and on first glance there are pretty nice things, like this:

Randomize a List<T>

But in my experience, at least on a fast machine, this is basically worthless. The shuffling works so fast that there is NOT a MS delay between two calls to Random.NEXT() which results in not nearly random behaviour.

I am NOT talking about super secure stuff, just a basic game random. I know I can add a delay of 1 MS, but this means "wasting" 200 MS just to randomize a list.

Now I found this approach: http://www.codinghorror.com/blog/2007/12/shuffling.html

It looks nice, using GUIDs to sort. BUT aren't they created the same way? Lets step it up a notch, lets assume I want to create 1000 numbers, between 0 - 5. This code is basically useless:

        var resultA = new List<int>();
        for (int i = 0; i < 1000; i++)
        {
            resultA.Add(new Random().Next(5));
        }


        var resultB = new List<int>();
        for (int i = 0; i < 1000; i++)
        {
            resultB.Add(new Random().Next(5));
            Thread.Sleep(1);
     开发者_如何学JAVA   }

A does not work at all, at least not im my environment in Windows Phone 7. B is fine, but it takes a second, which is also stupid. Any comments or thoughts, it can't be that hard to create a random list of integers :-)


Don't keep initializing a new instance of Random; make just one and continually reference it.

var random = new Random();
var resultA = new List<int>();
for (int i = 0; i < 1000; i++)
{
    resultA.Add(random.Next(5));
}

You are correct that repeatedly creating new instances of Random within the same "timestamp" will result in the same seed; but calling .Next on an instance of Random "advances" the seed so that the next number you retrieve is (most likely) different.

This is also covered in the documentation on Random:

... because the clock has finite resolution, using the parameterless constructor to create different Random objects in close succession creates random number generators that produce identical sequences of random numbers.

...

This problem can be avoided by creating a single Random object rather than multiple ones.


You need to keep hold of the same instance of Random.

    var random = new Random();

    var resultA = new List<int>();
    for (int i = 0; i < 1000; i++)
    {
        resultA.Add(random.Next(5));
    }


    var resultB = new List<int>();
    for (int i = 0; i < 1000; i++)
    {
        resultB.Add(random.Next(5));
        Thread.Sleep(1);
    }

This is because when Random initializes it uses the system clock to get a point in time. When you call next it can use the difference in time to get the next number. If you keep initializing a Random object you will keep getting the same number most of the time.


The shuffling works so fast that there is NOT a MS delay between two calls to Random.NEXT() which results in not nearly random behaviour.

What makes you think that there needs to be a ms delay between two calls to Random.Next?

Your bog standard random number generator is going to take some initial seed (say the system clock) and then repeatedly some algorithm to that seed to produce a sequence of numbers that appears to be random. Most of these algorithms don't take the clock as an input other than for the seed and so it doesn't matter how quickly two consecutive calls are executed.

The reason your code fails is because you keep instantiating a new random number generator on each iteration. This is where the clock can kill you because you end up with the same seed twice. You are not calling Random.Next consecutively on the same random number generator. You are calling Random.Next on a new random number generator on every iteration and sometimes these random number generators are seeded with the same value because you are seeding them by the system clock.

Move the instantiation of the random number generator outside of your loop.

var resultA = new List<int>();
Random rg = new Random();
for (int i = 0; i < 1000; i++) {
    resultA.Add(rg.Next(5));
}
0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜