Generating unique random numbers and date
While coding, once I needed the functionality of giving a random name to the files I was generating. So, I thought of deriving some random number and appending it to the existing file name since I didn’t want the file name to be appended by some sequential number. Moreover I have also used this random class to generate random password for my website.
NET Framework class library provides us with the Random class to generate random numbers. Random class has two overloaded constructors, one with no value and one with a seed value. We can not only derive random numbers from random class but also random bytes, random double number, random string etc. through its three public methods: Next, NextBytes, and NextDouble.
Next: returns a random number
NextBytes: returns random numbers in form of an array of bytes,
NextDouble returns a random number between 0.0 and 1.0.
Each of these methods has three overloaded forms allowing us to set the minimum and maximum range.
How to use Random class:
First define an instance of random class:
Random rand = new Random ();
Then use the methods as per your functionality
For ex:
int num = rand.Next(); // to return a random number
int num = rand.Next(500); // to returns a number between 0 and 500.
int num = rand.Next(100,500); //to returns a number between 100 and 500.
Generating random floating point numbers:
We can use the same random class to generate floating point numbers by calling its NextDouble method.
double dNum = rand.NextDouble();
Generating a random byte array
Similarly, we can create random bytes by calling the NextBytes method to populate a byte array.
byte[] ByteArray = new byte[65];
rand.NextBytes(ByteArray);
Array would be populated with random bytes of values between 0 and 255.
Now using the abve ways og generating random number, there is a big probability that we will get the same random number. One way to improve randomness is to make the seed value time dependent which means that there will be a problem only when the random methods is called at the same time. So, it is recommended to use the class-level Random field when you intend to generate the random number in the same time frame, such as within millisecond or within nanosecond. Also, random numbers cannot be used
In static environments unless you pass seed as a parameter but this would not be thread safe.
To generate the random number time dependent, you need to call an overloaded constructor passing some time unit as parameter. In below example we have passes ticks as parameter to the constructor:
Random rand = new Random((int)DateTime.Now.Ticks);
int num = rand.Next(1, 1000);
0
But suppose you need to generate not a single random number but hundreds of unique random number. Now if you run the above function in a loop of 50 iterations, then you will observe that the random number is not really unique. You can test it with the following array:
int[] arr = new int[100];
for (int i = 0; i < 100; i++)
\line Random rand = new Random((int)DateTime.Now.Ticks);
arr[i] = rand.Next(1, 10000);
0
When I run the above code, number stored in array is:
0
As you see above, numbers generated within the same time frame (ticks) is same. Since each instance of random class uses the same algorithm, each call to its Next method generates the same result as in the previous iteration as long as the seed does not change between the iterations.
So, in the above example, it means that for the first 32 iterations, seed was the same and the seed (Tick value) changed in the 33rd iteration and remained the same till the 100th iteration.
Now generating such a random number is of no use to us. So, to avoid generating such random numbers is to use the same instance while iterating, instead of creating a new instance for each iteration. So, now my code would look like:
int[] arr = new int[100];
rand = new Random((int)DateTime.Now.Ticks);
for (int i = 0; i < 100; i++)
{
arr[i] = rand.Next(1, 10000);
};
0If I run the above code, then i get the result as:
0
Notice the distinct values in the array
There are not much of the differences in both codes. In this case, I have kept seed as same for all iterations compared to only 32 iterations in the first scenario. But in this case, we reuse the random function to call the next random number for the same seed. So, Next method actually retrieves the “Next” value of the same seed.
Now let us define a simple function to derive unique random numbers so that same function is reused across different classes.
Below function will not work:
public int GetRandomInteger(int maxValue)
\line return new System.Random((int)System.DateTime.Now.Ticks).Next(1, maxValue);
0 Because the code is same like the first scenario where a new instance is used everytime.
So, let us tweak this function a little bit. Tweaked code looks like
public int GetRandomInteger(System.Random random, int maxValue)
\line return random.Next(1, maxValue);
0 As shown above, we would pass the instance of the random class as one of the parameter to generate unique random number.
This code would work for simple small applications but for large applications, how will you maintain the same instance variable across different projects. Moreover, you also need to create a new instance of Random class every time you need more random numbers.
So, we need a more reliable way of generating different seed value every time we create an instance of random class. To achieve this, we need to use RNGCryptoServiceProvider class of
System.Security.Cryptography namespace.
In the below code, we have used the getbytes function of RNGCryptoServiceProvider class to generate unique seed for deriving a strong sequence of random values.
public static int GetRandNum(int maxNum)
{
if (maxNum < 1)
throw new System.Exception(1 "The Number cannot be greater than 1");
byte[] b = new byte[4];
new RNGCryptoServiceProvider().GetBytes(b);
int iSeed = (b[0] & 0x7f) << 24 | b[1] << 16 | b[2] << 8 | b[3];
System.Random rand = new System.Random(iSeed);
return rand.Next(1, maxNum);
}
0
So, we have a method that reliably generates random integers. Consequently, it also solves a huge thread safety problem. Similarly, we can also generate distinct random double number and
Bytes as well.
This Random class can also be use to derive some random date as shown below:
Func<DateTime> RandomDay()
\line DateTime date = 2 new DateTime(3 2005, 3 1, 3 1);
Random rand = 2 new Random();
2 int dRange = ((TimeSpan)(DateTime.Today - date)).Days;
2 return () => date.AddDays(rand.Next(dRange));
We can also use an iterator to generate random date as shown below
2 static