Export (0) Print
Expand All

Random Class

Represents a pseudo-random number generator, a device that produces a sequence of numbers that meet certain statistical requirements for randomness.

To browse the .NET Framework source code for this type, see the Reference Source.

Namespace:  System
Assembly:  mscorlib (in mscorlib.dll)

[SerializableAttribute]
[ComVisibleAttribute(true)]
public class Random

The Random type exposes the following members.

  NameDescription
Public methodSupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsRandom()Initializes a new instance of the Random class, using a time-dependent default seed value.
Public methodSupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsRandom(Int32)Initializes a new instance of the Random class, using the specified seed value.
Top

  NameDescription
Public methodSupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsEquals(Object)Determines whether the specified object is equal to the current object. (Inherited from Object.)
Protected methodSupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsFinalizeAllows an object to try to free resources and perform other cleanup operations before it is reclaimed by garbage collection. (Inherited from Object.)
Public methodSupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsGetHashCodeServes as the default hash function. (Inherited from Object.)
Public methodSupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsGetTypeGets the Type of the current instance. (Inherited from Object.)
Protected methodSupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsMemberwiseCloneCreates a shallow copy of the current Object. (Inherited from Object.)
Public methodSupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsNext()Returns a nonnegative random integer.
Public methodSupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsNext(Int32)Returns a nonnegative random integer that is less than the specified maximum.
Public methodSupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsNext(Int32, Int32)Returns a random integer that is within a specified range.
Public methodSupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsNextBytesFills the elements of a specified array of bytes with random numbers.
Public methodSupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsNextDoubleReturns a random floating-point number between 0.0 and 1.0.
Protected methodSupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsSampleReturns a random floating-point number between 0.0 and 1.0.
Public methodSupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsToStringReturns a string that represents the current object. (Inherited from Object.)
Top

NoteNote

To view the .NET Framework source code for this type, see the Reference Source. You can browse through the source code online, download the reference for offline viewing, and step through the sources (including patches and updates) during debugging; see instructions.

Pseudo-random numbers are chosen with equal probability from a finite set of numbers. The chosen numbers are not completely random because a definite mathematical algorithm is used to select them, but they are sufficiently random for practical purposes. The current implementation of the Random class is based on Donald E. Knuth's subtractive random number generator algorithm. For more information, see D. E. Knuth. "The Art of Computer Programming, volume 2: Seminumerical Algorithms". Addison-Wesley, Reading, MA, second edition, 1981.

The random number generation starts from a seed value. If the same seed is used repeatedly, the same series of numbers is generated. One way to produce different sequences is to make the seed value time-dependent, thereby producing a different series with each new instance of Random. By default, the parameterless constructor of the Random class uses the system clock to generate its seed value, while its parameterized constructor can take an Int32 value based on the number of ticks in the current time. However, because the clock has finite resolution, using the parameterless constructor to create different Random objects in close succession creates random number generators that produce identical sequences of random numbers. The following example illustrates that two Random objects that are instantiated in close succession generate an identical series of random numbers.

byte[] bytes1 = new byte[100];
byte[] bytes2 = new byte[100];
Random rnd1 = new Random();
Random rnd2 = new Random();

rnd1.NextBytes(bytes1);
rnd2.NextBytes(bytes2);

Console.WriteLine("First Series:");
for (int ctr = bytes1.GetLowerBound(0); 
     ctr <= bytes1.GetUpperBound(0); 
     ctr++) { 
   Console.Write("{0, 5}", bytes1[ctr]);
   if ((ctr + 1) % 10 == 0) Console.WriteLine();
} 
Console.WriteLine();
Console.WriteLine("Second Series:");        
for (int ctr = bytes2.GetLowerBound(0);
     ctr <= bytes2.GetUpperBound(0);
     ctr++) {
   Console.Write("{0, 5}", bytes2[ctr]);
   if ((ctr + 1) % 10 == 0) Console.WriteLine();
}   
// The example displays the following output to the console: 
//       First Series: 
//          97  129  149   54   22  208  120  105   68  177 
//         113  214   30  172   74  218  116  230   89   18 
//          12  112  130  105  116  180  190  200  187  120 
//           7  198  233  158   58   51   50  170   98   23 
//          21    1  113   74  146  245   34  255   96   24 
//         232  255   23    9  167  240  255   44  194   98 
//          18  175  173  204  169  171  236  127  114   23 
//         167  202  132   65  253   11  254   56  214  127 
//         145  191  104  163  143    7  174  224  247   73 
//          52    6  231  255    5  101   83  165  160  231 
//        
//       Second Series: 
//          97  129  149   54   22  208  120  105   68  177 
//         113  214   30  172   74  218  116  230   89   18 
//          12  112  130  105  116  180  190  200  187  120 
//           7  198  233  158   58   51   50  170   98   23 
//          21    1  113   74  146  245   34  255   96   24 
//         232  255   23    9  167  240  255   44  194   98 
//          18  175  173  204  169  171  236  127  114   23 
//         167  202  132   65  253   11  254   56  214  127 
//         145  191  104  163  143    7  174  224  247   73 
//          52    6  231  255    5  101   83  165  160  231        

This problem can be avoided by creating a single Random object rather than multiple ones.

To improve performance, create one Random object to generate many random numbers over time, instead of repeatedly creating a new Random objects to generate one random number.

To generate a cryptographically secure random number suitable for creating a random password, for example, use a class derived from System.Security.Cryptography.RandomNumberGenerator such as System.Security.Cryptography.RNGCryptoServiceProvider.

The Random class and thread safety

Instead of instantiating individual Random objects, we recommend that you create a single Random instance to generate all the random numbers needed by your app. However, Random objects are not thread safe. If your app calls Random methods from multiple threads, you must use a synchronization object to ensure that only one thread can access the random number generator at a time. If you don't ensure that the Random object is accessed in a thread-safe way, calls to methods that return random numbers return 0.

The following example uses the C# lock Statement and the Visual Basic SyncLock statement to ensure that a single random number generator is accessed by 11 threads in a thread-safe manner. Each thread generates two million random numbers, counts the number of random numbers generated and calculates their sum, and then updates the totals for all threads when it finishes executing.

using System;
using System.Threading;

public class Example
{
   [ThreadStatic] static double previous = 0.0;
   [ThreadStatic] static int perThreadCtr = 0;
   [ThreadStatic] static double perThreadTotal = 0.0;  
   static CancellationTokenSource source;
   static CountdownEvent countdown; 
   static Object randLock, numericLock;
   static Random rand;
   double totalValue = 0.0;
   int totalCount = 0;

   public Example()
   { 
      rand = new Random();
      randLock = new Object();
      numericLock = new Object();
      countdown = new CountdownEvent(1);
      source = new CancellationTokenSource();
   } 

   public static void Main()
   {
      Example ex = new Example();
      Thread.CurrentThread.Name = "Main";
      ex.Execute();
   }

   private void Execute()
   {   
      CancellationToken token = source.Token; 

      for (int threads = 1; threads <= 10; threads++)
      {
         Thread newThread = new Thread(this.GetRandomNumbers);
         newThread.Name = threads.ToString();
         newThread.Start(token);
      }
      this.GetRandomNumbers(token);

      countdown.Signal();
      // Make sure all threads have finished.
      countdown.Wait();

      Console.WriteLine("\nTotal random numbers generated: {0:N0}", totalCount);
      Console.WriteLine("Total sum of all random numbers: {0:N2}", totalValue);
      Console.WriteLine("Random number mean: {0:N4}", totalValue/totalCount);
   }

   private void GetRandomNumbers(Object o)
   {
      CancellationToken token = (CancellationToken) o;
      double result = 0.0;
      countdown.AddCount(1);

      try { 
         for (int ctr = 0; ctr < 2000000; ctr++)
         {
            // Make sure there's no corruption of Random.
            token.ThrowIfCancellationRequested();

            lock (randLock) {
               result = rand.NextDouble();
            }
            // Check for corruption of Random instance. 
            if ((result == previous) && result == 0) {
               source.Cancel();
            }
            else {
               previous = result;
            }
            perThreadCtr++;
            perThreadTotal += result;
         }      

         Console.WriteLine("Thread {0} finished execution.", 
                           Thread.CurrentThread.Name);
         Console.WriteLine("Random numbers generated: {0:N0}", perThreadCtr);
         Console.WriteLine("Sum of random numbers: {0:N2}", perThreadTotal);
         Console.WriteLine("Random number mean: {0:N4}\n", perThreadTotal/perThreadCtr);

         // Update overall totals. 
         lock (numericLock) {
            totalCount += perThreadCtr;
            totalValue += perThreadTotal;  
         }
      }
      catch (OperationCanceledException e) {
         Console.WriteLine("Corruption in Thread {1}", e.GetType().Name, Thread.CurrentThread.Name);
      }
      finally {
         countdown.Signal();        
      }
   }
}
// The example displays output like the following: 
//       Thread 6 finished execution. 
//       Random numbers generated: 2,000,000 
//       Sum of random numbers: 1,000,491.05 
//       Random number mean: 0.5002 
//        
//       Thread 10 finished execution. 
//       Random numbers generated: 2,000,000 
//       Sum of random numbers: 999,329.64 
//       Random number mean: 0.4997 
//        
//       Thread 4 finished execution. 
//       Random numbers generated: 2,000,000 
//       Sum of random numbers: 1,000,166.89 
//       Random number mean: 0.5001 
//        
//       Thread 8 finished execution. 
//       Random numbers generated: 2,000,000 
//       Sum of random numbers: 999,628.37 
//       Random number mean: 0.4998 
//        
//       Thread Main finished execution. 
//       Random numbers generated: 2,000,000 
//       Sum of random numbers: 999,920.89 
//       Random number mean: 0.5000 
//        
//       Thread 3 finished execution. 
//       Random numbers generated: 2,000,000 
//       Sum of random numbers: 999,370.45 
//       Random number mean: 0.4997 
//        
//       Thread 7 finished execution. 
//       Random numbers generated: 2,000,000 
//       Sum of random numbers: 999,330.92 
//       Random number mean: 0.4997 
//        
//       Thread 9 finished execution. 
//       Random numbers generated: 2,000,000 
//       Sum of random numbers: 1,000,172.79 
//       Random number mean: 0.5001 
//        
//       Thread 5 finished execution. 
//       Random numbers generated: 2,000,000 
//       Sum of random numbers: 1,000,079.43 
//       Random number mean: 0.5000 
//        
//       Thread 1 finished execution. 
//       Random numbers generated: 2,000,000 
//       Sum of random numbers: 999,817.91 
//       Random number mean: 0.4999 
//        
//       Thread 2 finished execution. 
//       Random numbers generated: 2,000,000 
//       Sum of random numbers: 999,930.63 
//       Random number mean: 0.5000 
//        
//        
//       Total random numbers generated: 22,000,000 
//       Total sum of all random numbers: 10,998,238.98 
//       Random number mean: 0.4999

The example ensures thread-safety in the following ways:

  • The ThreadStaticAttribute attribute is used to define thread-local variables for the total of random numbers generated and their sum for each thread.

  • A lock protects access to the variables for the total count and sum of all random numbers generated on all threads.

  • A semaphore (the CountdownEvent object) is used to ensure that the main thread blocks until all other threads complete execution.

  • The example checks whether the random number generator has become corrupted by determining whether two consecutive calls to random number generation methods return 0. If corruption is detected, the example uses the CancellationTokenSource object to signal that all threads should be canceled.

  • Before generating each random number, each thread checks the state of the CancellationToken object. If cancellation is requested, the example calls the CancellationToken.ThrowIfCancellationRequested method to cancel the thread.

The following example is identical to the first, except that it uses a Task object and a lambda expression instead of Thread objects.

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

public class Example
{
   static Object randLock, numericLock;
   static Random rand;
   static CancellationTokenSource source;
   double totalValue = 0.0;
   int totalCount = 0;

   public Example()
   { 
      rand = new Random();
      randLock = new Object();
      numericLock = new Object();
      source = new CancellationTokenSource();
   } 

   public static void Main()
   {
      Example ex = new Example();
      Thread.CurrentThread.Name = "Main";
      ex.Execute();
   }

   private void Execute()
   {   
      List<Task> tasks = new List<Task>();

      for (int ctr = 0; ctr <= 10; ctr++)
      {
         CancellationToken token = source.Token; 
         int taskNo = ctr;
         tasks.Add(Task.Run( () =>
            {
               double previous = 0.0;
               int taskCtr = 0;
               double taskTotal = 0.0;  
               double result = 0.0;

               for (int n = 0; n < 2000000; n++)
               {
                  // Make sure there's no corruption of Random.
                  token.ThrowIfCancellationRequested();

                  lock (randLock) {
                     result = rand.NextDouble();
                  }
                  // Check for corruption of Random instance. 
                  if ((result == previous) && result == 0) {
                     source.Cancel();
                  }
                  else {
                     previous = result;
                  }
                  taskCtr++;
                  taskTotal += result;
               }

               // Show result.
               Console.WriteLine("Task {0} finished execution.", taskNo);
               Console.WriteLine("Random numbers generated: {0:N0}", taskCtr);
               Console.WriteLine("Sum of random numbers: {0:N2}", taskTotal);
               Console.WriteLine("Random number mean: {0:N4}\n", taskTotal/taskCtr);

               // Update overall totals. 
               lock (numericLock) {
                  totalCount += taskCtr;
                  totalValue += taskTotal;  
               }
            }, 
         token));
      }
      try {
         Task.WaitAll(tasks.ToArray());
         Console.WriteLine("\nTotal random numbers generated: {0:N0}", totalCount);
         Console.WriteLine("Total sum of all random numbers: {0:N2}", totalValue);
         Console.WriteLine("Random number mean: {0:N4}", totalValue/totalCount);
      }
      catch (AggregateException e) {
         foreach (Exception inner in e.InnerExceptions) {
            TaskCanceledException canc = inner as TaskCanceledException;
            if (canc != null)
               Console.WriteLine("Task #{0} cancelled.", canc.Task.Id);
            else
               Console.WriteLine("Exception: {0}", inner.GetType().Name);
         }         
      }           
   }
}
// The example displays output like the following: 
//       Task 1 finished execution. 
//       Random numbers generated: 2,000,000 
//       Sum of random numbers: 1,000,502.47 
//       Random number mean: 0.5003 
//        
//       Task 0 finished execution. 
//       Random numbers generated: 2,000,000 
//       Sum of random numbers: 1,000,445.63 
//       Random number mean: 0.5002 
//        
//       Task 2 finished execution. 
//       Random numbers generated: 2,000,000 
//       Sum of random numbers: 1,000,556.04 
//       Random number mean: 0.5003 
//        
//       Task 3 finished execution. 
//       Random numbers generated: 2,000,000 
//       Sum of random numbers: 1,000,178.87 
//       Random number mean: 0.5001 
//        
//       Task 4 finished execution. 
//       Random numbers generated: 2,000,000 
//       Sum of random numbers: 999,819.17 
//       Random number mean: 0.4999 
//        
//       Task 5 finished execution. 
//       Random numbers generated: 2,000,000 
//       Sum of random numbers: 1,000,190.58 
//       Random number mean: 0.5001 
//        
//       Task 6 finished execution. 
//       Random numbers generated: 2,000,000 
//       Sum of random numbers: 999,720.21 
//       Random number mean: 0.4999 
//        
//       Task 7 finished execution. 
//       Random numbers generated: 2,000,000 
//       Sum of random numbers: 999,000.96 
//       Random number mean: 0.4995 
//        
//       Task 8 finished execution. 
//       Random numbers generated: 2,000,000 
//       Sum of random numbers: 999,499.33 
//       Random number mean: 0.4997 
//        
//       Task 9 finished execution. 
//       Random numbers generated: 2,000,000 
//       Sum of random numbers: 1,000,193.25 
//       Random number mean: 0.5001 
//        
//       Task 10 finished execution. 
//       Random numbers generated: 2,000,000 
//       Sum of random numbers: 999,960.82 
//       Random number mean: 0.5000 
//        
//        
//       Total random numbers generated: 22,000,000 
//       Total sum of all random numbers: 11,000,067.33 
//       Random number mean: 0.5000

It differs from the first example in the following ways:

  • Because the variables to keep track of the number of random numbers generated and their sum in each task are local to the task, there is no need to use the ThreadStaticAttribute attribute.

  • The static Task.WaitAll method is used to ensure that the main thread doesn't complete before all tasks have finished. There is no need for the CountdownEvent object.

  • The exception that results from task cancellation is surfaced in the Task.WaitAll method. In the previous example, it is handled by each thread.

Notes to Callers

The implementation of the random number generator in the Random class isn't guaranteed to remain the same across major versions of the .NET Framework. As a result, you shouldn't assume that the same seed will result in the same pseudo-random sequence in different versions of the .NET Framework.

Notes to Inheritors

In the .NET Framework versions 1.0 and 1.1, a minimum implementation of a class derived from Random required overriding the Sample method to define a new or modified algorithm for generating random numbers. The derived class could then rely on the base class implementation of the Random.Next(), Random.Next(Int32), Random.Next(Int32, Int32), NextBytes, and NextDouble methods to call the derived class implementation of the Sample method.

In the .NET Framework version 2.0 and later, the behavior of the Random.Next(), Random.Next(Int32, Int32), and NextBytes methods have changed so that these methods do not necessarily call the derived class implementation of the Sample method. As a result, classes derived from Random that target the .NET Framework 2.0 and later should also override these three methods.

The following example creates a single random number generator and calls its NextBytes, Next, and NextDouble methods to generate sequences of random numbers within different ranges.

// Instantiate random number generator using system-supplied value as seed.
Random rand = new Random();
// Generate and display 5 random byte (integer) values. 
byte[] bytes = new byte[4];
rand.NextBytes(bytes);
Console.WriteLine("Five random byte values:");
foreach (byte byteValue in bytes)
   Console.Write("{0, 5}", byteValue);
Console.WriteLine();   
// Generate and display 5 random integers.
Console.WriteLine("Five random integer values:");
for (int ctr = 0; ctr <= 4; ctr++)
   Console.Write("{0,15:N0}", rand.Next());
Console.WriteLine();
// Generate and display 5 random integers between 0 and 100.//
Console.WriteLine("Five random integers between 0 and 100:");
for (int ctr = 0; ctr <= 4; ctr++)
   Console.Write("{0,8:N0}", rand.Next(101));
Console.WriteLine();
// Generate and display 5 random integers from 50 to 100.
Console.WriteLine("Five random integers between 50 and 100:");
for (int ctr = 0; ctr <= 4; ctr++)
   Console.Write("{0,8:N0}", rand.Next(50, 101));
Console.WriteLine();
// Generate and display 5 random floating point values from 0 to 1.
Console.WriteLine("Five Doubles.");
for (int ctr = 0; ctr <= 4; ctr++)
   Console.Write("{0,8:N3}", rand.NextDouble());
Console.WriteLine();
// Generate and display 5 random floating point values from 0 to 5.
Console.WriteLine("Five Doubles between 0 and 5.");
for (int ctr = 0; ctr <= 4; ctr++)
   Console.Write("{0,8:N3}", rand.NextDouble() * 5);
// Sample console output might appear as follows: 
//    Five random byte values: 
//      194  185  239   54  116 
//    Five random integer values: 
//        507,353,531  1,509,532,693  2,125,074,958  1,409,512,757    652,767,128 
//    Five random integers between 0 and 100: 
//          16      78      94      79      52 
//    Five random integers between 50 and 100: 
//          56      66      96      60      65 
//    Five Doubles. 
//       0.943   0.108   0.744   0.563   0.415 
//    Five Doubles between 0 and 5. 
//       2.934   3.130   0.292   1.432   4.369      

The following example generates a random integer that it uses as an index to retrieve a string value from an array.

using System;

public class Example
{
   public static void Main()
   {
      Random rnd = new Random();
      string[] malePetNames = { "Rufus", "Bear", "Dakota", "Fido", 
                                "Vanya", "Samuel", "Koani", "Volodya", 
                                "Prince", "Yiska" };
      string[] femalePetNames = { "Maggie", "Penny", "Saya", "Princess", 
                                  "Abby", "Laila", "Sadie", "Olivia", 
                                  "Starlight", "Talla" };                                      

      // Generate random indexes for pet names. 
      int mIndex = rnd.Next(malePetNames.Length);
      int fIndex = rnd.Next(femalePetNames.Length);

      // Display the result.
      Console.WriteLine("Suggested pet name of the day: ");
      Console.WriteLine("   For a male:     {0}", malePetNames[mIndex]);
      Console.WriteLine("   For a female:   {0}", femalePetNames[fIndex]);
   }
}
// The example displays the following output: 
//       Suggested pet name of the day: 
//          For a male:     Koani 
//          For a female:   Maggie

.NET Framework

Supported in: 4.5.2, 4.5.1, 4.5, 4, 3.5, 3.0, 2.0, 1.1, 1.0

.NET Framework Client Profile

Supported in: 4, 3.5 SP1

Portable Class Library

Supported in: Portable Class Library

.NET for Windows Store apps

Supported in: Windows 8

.NET for Windows Phone apps

Supported in: Windows Phone 8.1, Windows Phone 8, Silverlight 8.1

Windows Phone 8.1, Windows Phone 8, Windows 8.1, Windows Server 2012 R2, Windows 8, Windows Server 2012, Windows 7, Windows Vista SP2, Windows Server 2008 (Server Core Role not supported), Windows Server 2008 R2 (Server Core Role supported with SP1 or later; Itanium not supported)

The .NET Framework does not support all versions of every platform. For a list of the supported versions, see .NET Framework System Requirements.

Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.
Show:
© 2014 Microsoft