4

I have several processes in which I use System.Random's default constructor to generate random numbers. I read about it on MSDN but it dosn't say the specific system clock resolution it uses, for example does System.Random get the system clock seed in ms or seconds? Is it safe to use the default constructor across several process to get random values between them?

Cheers

KaiserJohaan
  • 9,028
  • 20
  • 112
  • 199
  • 1
    Have a look at this section from Jon Skeet's C# in Depth companion: [Random numbers](http://csharpindepth.com/Articles/Chapter12/Random.aspx) – Dave New Nov 06 '12 at 14:03

4 Answers4

3

The seed is in milliseconds in the range of 10 milliseconds to 16 milliseconds. But the most important thing to remember is that you should always use the same instance of Random if you can to generate different "random" values. If you always create a new instance in a tight loop you get the same value lots of times.

So it is "safe" to use the default constructor if you use the same instance anyway. If not because you need them in different threads, you can use this helper class from Jon Skeet(from here):

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;
        }
    }
}
Community
  • 1
  • 1
Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
  • the system.random() instances are unique per process, is that good enough? – KaiserJohaan Nov 06 '12 at 14:05
  • @KaiserJohaan Not sure what you mean. This code creates one instance per thread (Thanks to `[ThreadStatic]` on the field), which is required since `System.Random` isn't threadsafe. – CodesInChaos Nov 06 '12 at 14:07
  • To clarify, I have several process and in each I have one System.Random object to generate values. Will I get uniques? – KaiserJohaan Nov 06 '12 at 14:09
  • Can you clarify _process_, what kind of processes? If they are independent of each other they generate different(at least random) values. – Tim Schmelter Nov 06 '12 at 14:15
  • @KaiserJohaan Unique is not the same as random. If you create the Random objects within the same 10-16ms interval it's possible that they'll start with the same seed. You should use the non-default constructor to seed them, unless you don't plan to have them start creating random numbers at close to the same time. – Servy Nov 06 '12 at 14:39
3

it's uses the Environment.TickCount you can check it in Reflector. But the point is to get an unique seed, so you can use an arithmetic operation on this value with the ProcessID . like:

Random(Environment.TickCount + System.Diagnostics.Process.GetCurrentProcess().Id);

etc.

Jacob
  • 751
  • 1
  • 6
  • 18
2

If you are using different processes, consider using the process id to create the single instance of Random for each process.

private static readonly Random _theSingleRandom = 
                          new Random(Process.GetCurrentProcess().Id);
tallseth
  • 3,635
  • 1
  • 23
  • 24
  • 2
    May XOR it (or something) with a timestamp so it's still time-dependent? – Rawling Nov 06 '12 at 14:18
  • That sounds like the best suggestion so far. So essentially: private static readonly Random _theSingleRandom = new Random(Process.GetCurrentProcess().Id ^ Environment.TickCount); – Matthew Watson Nov 06 '12 at 15:01
0

System.Random uses the TickCount as its seed. The MSDN documentation at http://msdn.microsoft.com/en-us/library/windows/desktop/ms724408(v=vs.85).aspx states,

The resolution [...] is limited to the resolution of the system timer, which is typically in the range of 10 milliseconds to 16 milliseconds.

So there are 10 to 16 milliseconds between 2 different values of TickCount.

Roy Dictus
  • 32,551
  • 8
  • 60
  • 76