Sunday 28 July 2013

Microsoft internal Implementation of Random Class to Generate a Random Number

    

First we start with a sample of Random class, and Random number generation by called the Next Method.
In Random class we can call the default constructor or parameter constructor, to Initialize with seed value.


In Our First Example We are going to create a object with parameter constructor with seed value and invoke the Next Method which will give random number.

     static void Main(string[] args)
        {
            Random rand = new Random(20);
           
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine(rand.Next());
            }
        }


Next Method alone called with out specify the min and max value but class constructor intialize with seed value.

Output : 
1655911537
867932563
356479430
2115372437
234085668
658591161
1722583523
956804207
483147644
24066104


In Our Second example we can see the object of random class with default constructor and specify the min Value and Max Value in Next Method.

Specify the Min Value and Max Value in Next Method , With Default constructor Initialize.

      static void Main(string[] args)
        {
            Random rand = new Random();
           
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine(rand.Next(10,100));
            }
        }

 Output : 
72
95
34
23
32
38
94
76
10
22


Let we see the Real Implementation of random class and How it works .

How the object of Random class generates the Random Number, It Simple it takes the collection of values in array . On Constructor call the Random class initialize the int array with size of 56 with some values. the maximum value present in Random must be 2147483647 and seed is 161803398. 

The Constructor call make array filled with some random values whenever call to Next Method make the value to be fetch from the array and doing some arithmetic operations based on our input parameters, It is returning the value.

For Ex : In Next(10,100) It takes the difference between the number and multiply with another number , Another Number is framed by logic combination of multiple the value from array and  4.6566128752457969E-10, Due do this value value is reduced to 0.00... then Add to the MinValue. Now the Logic finally brings the value between the Min and Max.

C# Code 

using System;
using System.Runtime;
using System.Runtime.InteropServices;

namespace CustomRandomGenerator
{
       [Serializable]
       public class Random
       {
              private int inext;
              private int inextp;
              private int[] SeedArray = new int[56];
              private const int MBIG = 2147483647;
              private const int MSEED = 161803398;
              private const int MZ = 0;
             
              public Random() : this(Environment.TickCount)
              {
              }
             
              public Random(int Seed)
              {
                     int num = (Seed == -2147483648) ? 2147483647 : Math.Abs(Seed);
                     int num2 = 161803398 - num;
                     this.SeedArray[55] = num2;
                     int num3 = 1;
                     for (int i = 1; i < 55; i++)
                     {
                           int num4 = 21 * i % 55;
                           this.SeedArray[num4] = num3;
                           num3 = num2 - num3;
                           if (num3 < 0)
                           {
                                  num3 += 2147483647;
                           }
                           num2 = this.SeedArray[num4];
                     }
                     for (int j = 1; j < 5; j++)
                     {
                           for (int k = 1; k < 56; k++)
                           {
                                  this.SeedArray[k] -= this.SeedArray[1 + (k + 30) % 55];
                                  if (this.SeedArray[k] < 0)
                                  {
                                         this.SeedArray[k] += 2147483647;
                                  }
                           }
                     }
                     this.inext = 0;
                     this.inextp = 21;
                     Seed = 1;
              }
             
              protected virtual double Sample()
              {
                     return (double)this.InternalSample() * 4.6566128752457969E-10;
              }
              private int InternalSample()
              {
                     int num = this.inext;
                     int num2 = this.inextp;
                     if (++num >= 56)
                     {
                           num = 1;
                     }
                     if (++num2 >= 56)
                     {
                           num2 = 1;
                     }
                     int num3 = this.SeedArray[num] - this.SeedArray[num2];
                     if (num3 == 2147483647)
                     {
                           num3--;
                     }
                     if (num3 < 0)
                     {
                           num3 += 2147483647;
                     }
                     this.SeedArray[num] = num3;
                     this.inext = num;
                     this.inextp = num2;
                     return num3;
              }
             
              public virtual int Next()
              {
                     return this.InternalSample();
              }
             
              public virtual int Next(int minValue, int maxValue)
              {
                     if (minValue > maxValue)
                     {
                throw new ArgumentOutOfRangeException("minValue");
                     }
                     long num = (long)maxValue - (long)minValue;
                     if (num <= 2147483647L)
                     {
                           return (int)(this.Sample() * (double)num) + minValue;
                     }
                     return (int)((long)(this.GetSampleForLargeRange() * (double)num) + (long)minValue);
              }
             
              public virtual int Next(int maxValue)
              {
                     if (maxValue < 0)
                     {
                throw new ArgumentOutOfRangeException("maxValue");
                     }
                     return (int)(this.Sample() * (double)maxValue);
              }
             
              public virtual double NextDouble()
              {
                     return this.Sample();
              }
             
              public virtual void NextBytes(byte[] buffer)
              {
                     if (buffer == null)
                     {
                           throw new ArgumentNullException("buffer");
                     }
                     for (int i = 0; i < buffer.Length; i++)
                     {
                           buffer[i] = (byte)(this.InternalSample() % 256);
                     }
              }
              private double GetSampleForLargeRange()
              {
                     int num = this.InternalSample();
                     bool flag = this.InternalSample() % 2 == 0;
                     if (flag)
                     {
                           num = -num;
                     }
                     double num2 = (double)num;
                     num2 += 2147483646.0;
                     return num2 / 4294967293.0;
              }
       } 
}


From this Article, I Hope you got some clear understand about the random number generation using Random Class.