160

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?

4
  • 5
    Why? You can pass in a seed to the constructor. Do you really need to be able to reseed it? And why can't you just create a new one with the new seed? Commented Nov 23, 2009 at 20:38
  • I'm not complaining about the method/constructor design, but how people understand it. They only see "new Random()" and "r.Next" and think that it will choose a different seed for them, but it doesn't. Commented Nov 23, 2009 at 20:41
  • 8
    schnaader: People don't have a problem because they cannot reseed Random class. Their real problem is that they are misusing it. Commented Nov 23, 2009 at 20:43
  • 1
    /agree with Mehrdad. Adding a seed method, and reseeding in this example would not solve the problem. The seed is based on the timestamp, and given the fact that this code is run in a tight for loop, and the speed of modern computers, it will get reseeded at the same "time". The seeding has to be done once. Commented Nov 23, 2009 at 21:13

8 Answers 8

440

A good seed generation for me is:

Random rand = new Random(Guid.NewGuid().GetHashCode()); 

It is very random. The seed is always different because the seed is also random generated.

Sign up to request clarification or add additional context in comments.

16 Comments

+1 Elegant random generator! Thanks, this is what i was googling for.
Solved my problem two application being launched at the exact same time and getting the exact same seed value.
Technically a Guid based seed will not be random, but have a degree of uniqueness. Also the uniqueness is reduced by using GetHashCode() since a Guid can take more values than an int. For many, if not most, cases though, this is good enough.
Guid.NewGuid() actually has to use a random generator to create the GUID in the first place (along with other data such as time and location). Also it is slower than using new Random() without parameters, which sets the seed from the system time, and isn't any less random.
@ChrisNash System time is not random in the context of a loop. Why? Because it changes over time, and cumputers are generally damn fast! The reason OP got the same sequence is because the default constructor seeds with time, and the computer is so fast that time, measured in the precision of the system, does not measurably change while in the loop. So using time to seed multiple generators in tight succession is a common mistake.
|
128

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); 

3 Comments

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: 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.
Re-seeding a random generator may be required when predictibility becomes an issue (say. online gambling). In that case, apart from using a truer random generator (like a lava lamp), you should reseed faster than pattern recognition can apply from an attacker side - or use a pool of short-lived generators (and choose randomly, and ensure no two generators are seeded with the same value, and much more)
34

Bit late, but the implementation used by System.Random is Environment.TickCount:

public Random() : this(Environment.TickCount) { } 

This avoids having to cast DateTime.UtcNow.Ticks from a long, which is risky anyway as it doesn't represent ticks since system start, but "the number of 100-nanosecond intervals that have elapsed since 12:00:00 midnight, January 1, 0001 (0:00:00 UTC on January 1, 0001, in the Gregorian calendar)".

Was looking for a good integer seed for the TestApi's StringFactory.GenerateRandomString

3 Comments

If it's a testApi, just use the number 4, it's deterministic and easy to test
@hashtable that's often a good idea, but not all testing is unit testing. In system/integration testing introducing less predictable behaviour can increase the test surface - useful if you don't have the resources to check every possible input in a single test run.
We encountered problems in our app, where parallel threads were being released simultaneously (by accident), and the result was that the threads each got the same seed for random because they were triggered in the same tick. This doesn't seem to happen with the Guid trick.
18

In case you can't for some reason use the same Random again and again, try initializing it with something that changes all the time, like the time itself.

new Random(new System.DateTime().Millisecond).Next(); 

Remember this is bad practice though.

EDIT: The default constructor already takes its seed from the clock, and probably better than we would. Quoting from MSDN:

Random() : Initializes a new instance of the Random class, using a time-dependent default seed value.

The code below is probably your best option:

new Random().Next(); 

8 Comments

what about this? new Random(DateTime.Now.Millisecond).Next() As it gets the current milisecond. I like your idea of "initializing with something that changes all the time, like the time itself" though. Plus if we add a Thread.Sleep(1) in each iteration, it will be truely random.
You'll get a (little) better randomness by seeding Random with a larger not-too-predictable number, like new Random((int)DateTime.Now.Ticks)
I believe the default seed is ticks since system start time, anyway.
If the Random class is initialized multiple times in the same millisecond (like in a quick loop), this won't help at all. DateTime.Now.Ticks also doesn't update quickly enough.
The same problem as new Random(), which "Initializes a new instance of the Random class, using a time-dependent default seed value."
|
5
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.

5 Comments

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: Or worse; I've had it throw exceptions.
@Jason: in most cases, getting an exception is better than dealing with bad results. I'd rather have my online poker application crashing than being easily predictable
@PPC in that scenario you should go for crypto random
The OP said nothing about thread safety. Just calling fast.
3

A good seed initialisation can be done like this

Random rnd = new Random((int)DateTime.Now.Ticks); 

The ticks will be unique and the cast into a int with probably a loose of value will be OK.

1 Comment

Not so unique as you might like to think.
0

this workes for me:

private int GetaRandom() { Thread.Sleep(1); return new Random(DateTime.Now.Millisecond).Next(); } 

1 Comment

Putting the current thread to sleep can cause a multitude of problems with concurrency. You're essentially locking the current thread you're working with, which I suspect in most cases will be your main application thread. To make this work, I would suggest isolating your RNG into it's own thread, so that it can be considered thread-safe, and using it asyncronously.
-2

I use this for most situations, keep the seed if there is a need to repeat the sequence

 var seed = (int) DateTime.Now.Ticks; var random = new Random(seed); 

or

 var random = new Random((int)DateTime.Now.Ticks); 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.