views:

422

answers:

3

i have the following code inside a static method in a static class

Random r = new Random();
int randomNumber = r.Next(1,100);

i have this inside a loop and i keep getting the same randomNumber?

any suggestions here?

+8  A: 

You should not create a new Random instance in a loop. Try something like:

var rnd = new Random();
for(int i = 0; i < 100; ++i) 
   Console.WriteLine(rnd.Next(1, 100));

The sequence of random numbers generated by a single Random instance is supposed to be uniformly distributed. By creating a new Random instance for every random number in quick successions, you are likely to seed them with identical values and have them generate identical random numbers. Of course, in this case, the generated sequence will be far from uniform distribution.

For the sake of completeness, if you really need to reseed a Random, you'll create a new instance of Random with the new seed:

rnd = new Random(newSeed);
Mehrdad Afshari
Hi, I have got a confusion about the word 'Seed', How does it work? and what is the impact that it has on the Random Class in Java.util
harigm
@harigm: Normally, a (pseudo-)random number generator is a deterministic algorithm that given an initial number (called *seed*), generates a sequence of numbers that adequately satisfies statistical randomness tests. Since the algorithm is deterministic, the algorithm will always generate the exact same sequence of numbers if it's initialized with the same seed. That's why system time (something that changes all the time) is usually used as the seed for random number generators.
Mehrdad Afshari
+3  A: 
public static Random rand = new Random(); // this happens once, and will be great at preventing duplicates

Note, this is not to be used for cryptographic purposes.

McKay
Note that unlike Java, `Random` in .NET is not thread-safe. Calling `Next` without appropriate locking mechanisms on different threads might cause corruption of the internal state of the random number generator.
Mehrdad Afshari
@Mehrdad: Or worse; I've had it throw exceptions.
Jason
+4  A: 

Generally the best idea is to have a single instance of Random per thread - you don't want to create an instance regularly as you'll end up with repeats as you've seen, and you don't want to reuse instances between threads as Random isn't thread-safe.

Here's a little class to help with that:

using System;
using System.Threading;

public static class RandomHelper
{
    private static int seedCounter = new Random().Next();

    [ThreadStatic]
    private static Random rng;

    public static Random Instance
    {
        get
        {
            if (rng == null)
            {
                int seed = Interlocked.Increment(ref seedCounter);
                rng = new Random(seed);
            }
            return rng;
        }
    }
}

You can then safely use RandomHelper.Instance from any thread. Ideally, for testability, you should try to use this relatively rarely - treat randomness as a dependency, and pass the Random reference into methods that need it.

Note that:

  • The rng field has the [ThreadStatic] attribute applied to it, so it's effectively a different variable for each thread.
  • We initialize seedCounter (once) based on the current time, but then increment it in a thread-safe manner each time we need a new instance for another thread.
Jon Skeet