System.Random default constructor system clock resolution? - c#

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

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.

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

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

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.

Related

Generating random values in static methods seem to cache [duplicate]

This question already has answers here:
Random.Next returns always the same values [duplicate]
(4 answers)
Closed 8 years ago.
I have a static method in a static class which can generate random strings, like this:
public static class DataGenerator
{
public static string GenerateRandomString(int length)
{
const string Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
var random = new Random();
return new string(
Enumerable.Repeat(Chars, length)
.Select(s => s[random.Next(s.Length)])
.ToArray());
}
}
When I call this method multiple times from the same calling function, it seems to cache the generated string.
Here is an example of usage:
var item = new CodeDescActivePo()
{
Active = true,
Code = DataGenerator.GenerateRandomString(10),
Description = DataGenerator.GenerateRandomString(10)
};
Notice that there are 2 calls to GenerateRandomString, I would expect 2 unique random numbers, in this case Code and Description are always the same.
Why would GenerateRandomString not generate a fresh random number each time?
You are calling var random = new Random(); too quickly together. Since the default seed is time based, the seed is the same. Better to create this variable once and Random.Next() every time you need it.
public static class DataGenerator
{
private readonly static Random random = new Random();
public static string GenerateRandomString(int length)
{
//etc etc using random.Next()
}
}
Because you are using a new Random() instance for each call. By default it is seeded with the current system time, which means that multiple Random instances created at the same time will give the same values.
Make the Random instance a static field instead to keep it alive between the calls.
Problem:
From MSDN
The default seed value is derived from the system clock and has finite resolution. As a result, different Random objects that are created in close succession by a call to the default constructor will have identical default seed values and, therefore, will produce identical sets of random numbers.
Solution: Again from MSDN
This problem can be avoided by using a single Random object to generate all random numbers. You can also work around it by modifying the seed value returned by the system clock and then explicitly providing this new seed value to the Random(Int32) constructor. For more information, see the Random(Int32) constructor.

How do I make my C# random number generator change with each time the constructor is called?

I have two classes, a Teacher class and a Student class. In my program I create an array of 10 Teacher objects and within each Teacher object is an array of 10 Student Objects. Each Student object also has an array of integers as a member variabe, and when each Student is instantiated, it's own array of integers are filled with numbers from a random number generator. My program goes something like this:
An array of type Teacher is created with size 10
The array is then filled with 10 actual teacher objects
Each Teacher object contains an array of Student objects of size 10 as a member variable
The Student array in each Teacher object is filled with actual Student objects
Each student object has an array of integers that are filled with random numbers in the Student objects constructor.
Here is the problem I ran into: It seems that every time the 10 Student objects are created for each Teacher, the random number generator within the Student object constructor does not reset or change even when I call the .Next() function until the next set of 10 Student objects are created for the next Teacher object. What I want is the 10 Teacher objects to each have their own Student Objects which have their own integer arrays filled with randomly generated numbers.
Any help would be appreciated! I ran into this sort of problem with constructors with my last question, and that was a matter of whether something was to be static or not and I'm not sure that's the case this time. Please ask me questions if I wasn't clear enough about anything!!
UPDATE** So after looking at MSDN, I found in their sample code "Thread.Sleep(2000)" and stuck it into my Student Constructor just to see what it did. It seemed to have solved the problem although my program runs a lot slower now, is there a minimum sleep value to wait until the Random.Next() uses a new seed from the clock and even if I did solve the problem, is there a better way to do this? My random number generator is already a static member variable of Student.
If you initialize several Random instances using the default constructor, Random(), within a short time period, then you risk that they would end up with the same seed value (which is time-dependant) and, therefore, generate the same random sequence each time.
You can fix this issue by initializing a single static Random instance, and share it among all Student instances. This is perfectly safe as long as you’re not multi-threading.
public class Student
{
private static readonly Random random = new Random();
}
From the MSDN page on the Random() constructor:
The default seed value is derived from the system clock and has finite resolution. As a result, different Random objects that are created in close succession by a call to the default constructor will have identical default seed values and, therefore, will produce identical sets of random numbers. This problem can be avoided by using a single Random object to generate all random numbers. You can also work around it by modifying the seed value returned by the system clock and then explicitly providing this new seed value to the Random(Int32) constructor. For more information, see the Random(Int32) constructor.
Edit: Although you state that your random number generator is already a static member, this is still not enough if you’re instantiating it repeatedly (redundantly) during each Student initialization. The following code is still incorrect:
public class Student
{
private static Random random;
private int[] numbers;
public Student()
{
random = new Random();
numbers = new int[10];
for (int i = 0; i < 10; ++i)
numbers[i] = random.Next();
}
}
You need to replace it with a version that only instantiates Random once, like so:
public class Student
{
private static readonly Random random = new Random();
private int[] numbers;
public Student()
{
numbers = new int[10];
for (int i = 0; i < 10; ++i)
numbers[i] = random.Next();
}
}
A common pitfall with Random is to create a new instance each time you need a random value.
for (int i = 0; i < 1000; i++) {
var random = new Random();
list.Add(random.Next());
}
This does not work as expected, since Random uses the actual time to create the first random value. However, the time clock has a limited resolution. It can be that several succeeding iterations return the same time and thus the same (pseudo) random value!
The solution is to create random only once.
var random = new Random();
for (int i = 0; i < 1000; i++) {
list.Add(random.Next());
}
You could also declare random as a static class member
public static readonly Random RandomGenerator = new Random();
A random number generator uses the system time as a seed. I wonder if you are possibly declaring a new generator and calling it before the system has time to move on to its next increment. The processor cycles are actually more than often faster than the system clock. Can you post a code example?
I would suggest declaring a Static generator as either a class property or somewhere else accessible, instantiate it as final. This will guarantee that you wont be overwriting the generator with another.

C# Random Number Generator getting stuck in a cycle

I am using .NET to create an artificial life program and I am using C#'s pseudo random class defined in a Singleton. The idea is that if I use the same random number generator throughout the application, I could merely save the seed and then reload from the seed to recompute a certain interesting run.
public sealed class RandomNumberGenerator : Random
{
private static readonly RandomNumberGenerator instance = new RandomNumberGenerator();
RandomNumberGenerator()
{
}
public static RandomNumberGenerator Instance
{
get
{
return instance;
}
}
}
I also wanted a method that could give me two different random numbers.
public static Tuple<int, int> TwoDifferentRandomNumbers(this Random rnd, int minValue, int maxValue)
{
if (minValue >= maxValue)
throw new ArgumentOutOfRangeException("maxValue", "maxValue must be greater than minValue");
if (minValue + 1 == maxValue)
return Tuple.Create<int, int>(minValue, maxValue);
int rnd1 = rnd.Next(minValue, maxValue);
int rnd2 = rnd.Next(minValue, maxValue);
while (rnd1 == rnd2)
{
rnd2 = rnd.Next(minValue, maxValue);
}
return Tuple.Create<int, int>(rnd1, rnd2);
}
The problem is that sometimes rnd.Next(minValue,maxValuealways returns minValue. If I breakpoint at this point and try creating a double and setting it to rnd.NextDouble(), it returns 0.0. Anyone know why this is happening?
I know that it is a pseudo random number generator, but frankly, I hadn't expected it to lock at 0. The random number generator is being accessed from multiple threads... could this be the source of the problem?
EDIT : Thanks, the problem ended up being thread safety.
This is the new version of the class.
public sealed class RandomNumberGenerator : Random
{
private static Random _global = new Random();
[ThreadStatic]
private static Random _localInstance;
RandomNumberGenerator()
{
}
public static Random Instance
{
get
{
Random inst = _localInstance;
if (inst == null)
{
int seed;
lock (_global) seed = _global.Next();
_localInstance = inst = new Random(seed);
}
return _localInstance;
}
}
}
The Random class is not thread-safe.
You should make your static instance [ThreadStatic], or protect it with a lock.
If you use only One RNG for multiple threads even if you save the seed, you won't be able to generate the same numbers the next time you launch your application because you won't be sure that the calls to the RNG from the different threads will be in the same order.
If you have a fixed/known number of thread make a RNG per Thread and save each seed.
Forget what I just said if you're 100% sure that each thread will call the RNG with exactly the same order as the last time if you use the same seed.
The idea is that if I use the same random number generator throughout the application, I could merely save the seed and then reload from the seed to recompute a certain interesting run.
You don't actually need a singleton instance of the RNG for this. If you initialize two separate instances of Random to the same seed, they will produce exactly the same sequence.
My advice is, save the seed, but get rid of the singleton.
I don't even have to look up the Random class th know "all instance methods of this class or not thread-safe". That goes for all .NET classes, with a very few exceptions.
So yes, it is the multi-threading. But you haven't mentioned verifying that MaxValue > MinValue either.

How can I get a random time between Now and some previous time point (eg. 1 hour ago)?

I'm trying to make an extension method that allows me to create a random time between Now and some user requested historical time point in the form of a TimeSpan.
For example : a random time between now and 1 hour ago.
So, I came up with the following Random(..) extension method.
I thought to make the random seed NOT static, but if i call this method a LOT and QUICKLY (eg. in a loop), then I thought the seed (which is based on time) isn't really random for really fast calls. is that true? (it seems to be, when i check my results)
public static DateTimeOffset Random(this DateTimeOffset value, TimeSpan timeSpan)
{
var random = new Random();
DateTimeOffset minDateTime = value.Subtract(timeSpan);
int range = ((DateTime.Today - minDateTime)).Hours;
return minDateTime.AddHours(random.Next(range));
}
As others have said, the problem is that new Random() uses the current time to form the seed, and you're getting the same one lots of times.
Basically you want to create relatively few instances. As Random isn't thread-safe, you need ThreadStatic or ThreadLocal<T> - the latter is new to .NET 4.0. Here's a sample StaticRandom class (using .NET 4.0) which lets you use the Instance property to get a valid instance for this thread. Note that on type initialization, a counter is set from the current time. This is then used for successive seeds.
using System;
using System.Threading;
public static class StaticRandom
{
private static int seed;
private static ThreadLocal<Random> threadLocal = new ThreadLocal<Random>
(() => new Random(Interlocked.Increment(ref seed)));
static StaticRandom()
{
seed = Environment.TickCount;
}
public static Random Instance { get { return threadLocal.Value; } }
}
Then you can just use StaticRandom.Instance whenever you need an instance of Random.
Now to get back to the original question, it's not entirely clear what your current extension method is doing. Why are you using DateTime.Today at all? I suspect you want something like:
public static DateTimeOffset Random(this DateTimeOffset value, TimeSpan timeSpan)
{
double seconds = timeSpan.TotalSeconds * StaticRandom.Instance.NextDouble();
// Alternatively: return value.AddSeconds(-seconds);
TimeSpan span = TimeSpan.FromSeconds(seconds);
return value - span;
}
However, that will give you a completely random time - it's almost bound to be part way through a millisecond, for instance. Is that okay, or do you effectively want it to be an exact number of seconds (or minutes, or hours) based on the original timespan?
Use a Random object that's created/initialised once and not every time the method is called. Another option is to pass a Random instance into the method when you call it.
You could also create overloads that allow you to do either of the above options:
public static DateTimeOffset Random(this DateTimeOffset value, TimeSpan timeSpan)
{
if (_threadStaticRng == null)
_threadStaticRng = new Random();
return value.Random(timeSpan, _threadStaticRng);
}
public static DateTimeOffset Random(
this DateTimeOffset value, TimeSpan timeSpan, Random rng)
{
DateTimeOffset minDateTime = value.Subtract(timeSpan);
int range = ((DateTime.Today - minDateTime)).Hours;
return minDateTime.AddHours(rng.Next(range));
}
[ThreadStatic]
private static Random _threadStaticRng;
You have to seed the Random number generator. A good practice would be to do the following:
var random = new Random((int)DateTime.Now.Ticks);
This should make it more random for you.
You could also create the Random generator as a static class variable so you don't have to instantiate it every time.

Random behavior differences between C# and Java: the seed

I have a Random into a class which aims to generate random sequences in different contexts: this is the result of a porting from Java code.
In the Java version everything works fine since the java.lang.Random class has the method setSeed, which permits the change of the seed value dynamically.
Random rnd = new Random();
...
rnd.nextInt();
...
rnd.setSeed(seedValue);
This generates a consistent result, since each time the seed value is set, the result is random.
Unfortunately in C# the behavior is much different, since the Random class needs the seed to be set at construction:
Random rnd = new Random(seedValue);
...
rnd.Next();
...
So I have to build a new Random instance each time with the given seed, which in some spare cases generates the same value of a previous call.
Is it a way to set the seed of a Random instance in C# dynamically, without losing the consistency of the instance globally?
Thank you very much!
Typically I create a single instance of Random for my application and after setting the seed on instantiation can rely on each call to Next giving me a new random number. The trick is to make sure the seed is as random as possible. The use of Random in a C# app is a good example of where a Singleton is a good fit.
There are a variety of ways to get differing strengths of randomness in your seed and there are some good SO questions dealing with that.
The example below is the approach I use.
m_randomURL = "https://www.random.org/cgi-bin/randnum?num=1&min=1&max=1000000000";
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(m_randomURL);
StreamReader stIn = new StreamReader(req.GetResponse().GetResponseStream());
Random rand = new Random(Convert.ToInt32(stIn.ReadToEnd()));
random.org uses atmospheric noise to generate the randomness and is apparently used for lotteries and such.
First of all, I wouldn't expect to have setSeed called more than once on a Random during runtime. FreeCell does it so that you can "load" game instances by writing down the seed that was used.
If you change seeds, it should be like resetting the Random instance and thus there should be no conflict if you reinstanciate it. Random is just a wrapper on an underlying algorithm.
If you want to receive different results each time (even if you USE setSeed), you might try this:
class MyRandom {
private Random random = new Random(DateTime.Now.Ticks);
public void setSeed(long seed) {
random = new Random(seed * this.random.next());
...
public long next() {
return random.next();
}
class MyClass {
private MyRandom random = new MyRandom();
public void Test() {
random.setSeed(seedValue);
int x = random.next();
random.setSeed(seedValue);
int y = random.next();
// x,y will be different in most of the cases now
}
}
This will change pre/postconditions of how seeds for random generators should work but might work for you.
try to wrap the Random instance, as pseudocode:
class MyRandom {
private Random random;
public void setSeed(long seed) {
random = new Random(seed);
...
public long next() {
return random.next();

Categories