All posts tagged 'C'

.NET Musings

Wandering thoughts of a developer, architect, speaker, and trainer

NAVIGATION - SEARCH

Random Numbers in C#

When is a Random number not truly Random? When it's generated through the System.Random class. This class takes an optional seed value, but returns essentially a predefined order of seemingly random numbers.

The (non)Random Class

To prove this case, run the following code which uses the default constructor of the Random class:

  1: while (true)
  2: {
  3:   Random r = new Random();
  4:   Console.Write(r.Next() + ":");
  5:   Console.WriteLine(r.Next());
  6:   string test = Console.ReadLine();
  7:   if (test=="q") { return; }
  8: }
  9: 
The generated results look will like something like this:
1161903818:2056898737

1963702974:413464101

1466546674:234618278

Now, change the code to include a seed value in the constructor for the Random class:


  1: while (true)
  2: {
  3:   Random r = new Random(1234);
  4:   Console.Write(r.Next() + ":");
  5:   Console.WriteLine(r.Next());
  6:   string test = Console.ReadLine();
  7:   if (test=="q") { return; }
  8: }
  9: 

You will see that the Randomness isn't there anymore. The results from this run are far from Random!
857109877:1923929452

857109877:1923929452

857109877:1923929452

This tells us that the parameter-less constructor is using some internal generation algorithm to seed to class. In fact, if we fire of a series of New/Next commands within the loop, we will see a set number of the generations will repeat themselves before rotating to a new set. The seed is obviously generated from CPU ticks or the system clock or some other factor of time.


The nice part of this class is that you can pass in a Min and a Max to the Next method. If you don't need a cryptographically strong random number, this should work fine.


Using RNGCryptoServiceProvider for True(r) Randomness


The .Net Framework comes with one concrete implementation of System.Security.Cryptography.RandomNumberGenerator, and that is the RNGCryptoServiceProvider. While I don't want to get into a debate on how truly random the RNG Provider is, it is generally accepted as a cryptographically strong Random Number Generator. Please check with your security group prior to generating any code for security measures to make sure you are within the security teams guidelines.


There is a bit more code involved in using this class, but it is well worth the extra effort. The code looks like this:


  1: while (true)
  2: {
  3:   int max = 10000;
  4:   int min = 1;
  5:   RNGCryptoServiceProvider c = new RNGCryptoServiceProvider();
  6:   for (int x = 0; x < 20; x++)
  7:   {
  8:     // Create a byte array to hold the random values.
  9:     byte[] randomNumber = new byte[4];
 10:     // Fill the array with a random value.
 11:     c.GetBytes(randomNumber);
 12:     //Convert to a number
 13:     int result = Math.Abs(BitConverter.ToInt32(randomNumber, 0));
 14:     Console.WriteLine(result % max + min);
 15:   }
 16:   string test = Console.ReadLine();
 17:   if (test == "q") { return; }
 18: }
 19: 

The byte array length determines "how many cryptographically strong random bytes are produced" (VS2008 Documentation). To create a Random Number within a range of values, look at Line 15 of the code sample, where it is converting the full random number generated to a number between 1 and 10,000.


Hopefully this clears up the difference between the Random class and the RNGCryptoServiceProvider class, and the degree of randomness.


Happy Coding!




Managed Windows Shared Hosting by OrcsWeb