Getting random values

Date posted: 14/05/2017

Name:

*

My email:

*

Recipient email:

*

Message:

*

Fields marked as bold are compulsory.

You haven't filled in compulsory values.The email is not correct

You do not have to be working on some gambling project in order to request for a random number. Things like that happen all the time. Either you may need to pick a random product to show out of a list or you may want to present some results randomly ordered. Anyway, getting a random number is something you will need to do from time to time. To get a random number we may use the Random or the RNGCryptoServiceProvider class. We are going to find out what is the difference between them and talk about what makes a random number.

Randomness

Let's start with the basics. What makes a random number? A number is considered random when there is no method to predict what that will be before it is presented. You may think of this as something obvious, however it is not.

Let's say someone asked you to pick a number between 1 and 10 and you picked 5. Why would that be? Maybe that is because you like number 5, or you like the fact it is located in the middle of the 1 to 10 range, or because of a subconscious thought of the 5 euro note you were holding a while ago, or well, pretty much anything. Not being able to predict the number you are going to pick, makes it quite a random guess.

However, no matter why you have chosen number five, there will always be some reason why you picked that number. A person may be able to locate that reason and from that moment on be able to predict what number you are going to pick at given circumstances If the value of the cause and the way it affects the result number is easy to guess, this makes your number pseudo-random.

The value of the reason that causes the number to be selected is called seed.

So a random number will never be 100% pure random. However, the less easy to compute the seed, the more random it will be. In case you've been wondering what all this fuss is about, that's because Random class is far more pseudo-random than RNGCryptoServiceProvider. And we are now going to see the reason why.

Using the Random class

To use the Random we first have to create an object instance like this

Random rnd = newRandom();

After that, there are a few handful methods we can use to get our random values. For example

//Get a random integer greater than or equal to 0

int random = rnd.Next();

//Get a random integer greater than or equal to 0 and less than 100

int random = rnd.Next(100);

//Get a random integer greater than or equal to -10 and less than 100

int random = rnd.Next(-10, 100);

//Get a random floating point number greater than or equal to 0 and less than 1

double random = rnd.NextDouble();

//Get a random 32-bit integer than or equal to 0

double random = rnd.NextDouble() * Int32.MaxValue;

By using the Next method (or a similar one) we get a new random value generated by our Random object.

Now, there are two ways to instantiate a Random object. One is the default one we used earlier

Random rnd = newRandom ();

The other one is using a seed of our own by setting an integer argument to the constructor like that.

Random rnd = newRandom (5);

What should be taken into account here is that Random objects initialized using the same seed will produce the same results.

Random rnd = newRandom(5);

Random rnd2 = newRandom(5);

int random11 = rnd.Next();

int random21 = rnd2.Next();

int random12 = rnd.Next();

int random22 = rnd2.Next();

//random1 equals random21 and random12 equals random22

So Random will produce no actual random results, rather it is considered a pseudo-random method since its integer seed is responsible for all results.

So, how about using the default constructor?

Random rnd = newRandom();

In case we feed no seed to Random, it gets its own value from the CPU-clock time value. In that case, things are not as bad as when we use our own seed, since time values can vary. Still it is not considered actual random since, as mentioned, some easy to guess seed determines all results. Actually if you find out a few results created, you can even predict what the next result will be even before it pops up.

Also, take a look at the following example.

var randoms = new int[5];

for (int i = 0; i < randoms.Length; i++)

{

Random rnd = newRandom();

randoms[i] = rnd.Next();

}

Since each of my loops takes a tiny amount of time to complete, all rnd objects we create use the same seed. As a result all values in the randoms array are equal. To avoid this we should have created one Random object and then use Next on the loop like this.

var randoms = new int[5];

Random rnd = newRandom();

for (int i = 0; i < randoms.Length; i++)

randoms[i] = rnd.Next();

You may now be wondering, is there any point in using the constructor that takes a seed, if it makes things far less random than the default constructor does? Well, not much, but you can use it, if you want to test your random methods more than once so they will return the same values every time.

So, using Random is ok when we need a few random values that we do not mind if they are not actually random. And this applies perfectly most of the times. Actually, I've never found myself in need of more than that. However there are times we do need something more. This is where RNGCryptoServiceProvider comes into play.

Using the RNGCryptoServiceProvider class

RNGCryptoServiceProvider located in the System.Security.Cryptography will implement a cryptographic Random Number Generator using the implementation provided by the cryptographic service provider. What is the meaning of all that? Simply put, RNGCryptoServiceProvider uses OS Entropy as a seed. That OS Entropy is a value produced by things like keyboard timings, thermal temp, sound etc so it can be really hard to predict. As a result this makes it quite a random value generator.

We can use RNGCryptoServiceProvider like this.

using (var rng = new RNGCryptoServiceProvider())

{

byte[] bytesArray = new byte[5];

rng.GetBytes(bytesArray);

int randomvalue = BitConverter.ToInt32(bytesArray, 0);

}

Even though RNGCryptoServiceProvider generates random results, using it instead of Random all the time is not a good idea since it is slower. If you do not wish to go for totally random values, stick to the simpler Random class.

It is also worth mentioning that the random number generators we described provide random (or pseudo-random numbers). However, randomness should not be mistaken with uniqueness. That means that a random generator does not necessarily produce unique numbers, even though it may be quite unusual to get two equal numbers one after the other in a sequence. To face the uniqueness problem we can use GUIDs which on the contrary are meant to be unique but not random. You can read this article of mine concerning GUIDs if you wish to learn more.

Summary

To generate random values we can use either the Random or the RNGCryptoServiceProvider class. Random is actually a pseudo-random generator based on its initialization seed. On the other hand RNGCryptoServiceProvider creates actual random values.