5 out of 10 rated this helpful Rate this topic

Random Class

Updated: March 2011

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

System.Object
  System.Random

Namespace:  System
Assembly:  mscorlib (in mscorlib.dll)
[SerializableAttribute]
[ComVisibleAttribute(true)]
public class Random

The Random type exposes the following members.

  Name Description
Public method Supported by the XNA Framework Supported by Portable Class Library Random Initializes a new instance of the Random class, using a time-dependent default seed value.
Public method Supported by the XNA Framework Supported by Portable Class Library Random(Int32) Initializes a new instance of the Random class, using the specified seed value.
Top
  Name Description
Public method Supported by the XNA Framework Supported by Portable Class Library Equals(Object) Determines whether the specified Object is equal to the current Object. (Inherited from Object.)
Protected method Supported by the XNA Framework Supported by Portable Class Library Finalize Allows an object to try to free resources and perform other cleanup operations before it is reclaimed by garbage collection. (Inherited from Object.)
Public method Supported by the XNA Framework Supported by Portable Class Library GetHashCode Serves as a hash function for a particular type. (Inherited from Object.)
Public method Supported by the XNA Framework Supported by Portable Class Library GetType Gets the Type of the current instance. (Inherited from Object.)
Protected method Supported by the XNA Framework Supported by Portable Class Library MemberwiseClone Creates a shallow copy of the current Object. (Inherited from Object.)
Public method Supported by the XNA Framework Supported by Portable Class Library Next Returns a nonnegative random number.
Public method Supported by the XNA Framework Supported by Portable Class Library Next(Int32) Returns a nonnegative random number less than the specified maximum.
Public method Supported by the XNA Framework Supported by Portable Class Library Next(Int32, Int32) Returns a random number within a specified range.
Public method Supported by the XNA Framework Supported by Portable Class Library NextBytes Fills the elements of a specified array of bytes with random numbers.
Public method Supported by the XNA Framework Supported by Portable Class Library NextDouble Returns a random number between 0.0 and 1.0.
Protected method Supported by the XNA Framework Supported by Portable Class Library Sample Returns a random number between 0.0 and 1.0.
Public method Supported by the XNA Framework Supported by Portable Class Library ToString Returns a string that represents the current object. (Inherited from Object.)
Top

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 a modified version of 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.

Notes to Callers

The implementation of the random number generator in the Random class is not guaranteed to remain the same across major versions of the .NET Framework. As a result, your application code should not 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      


.NET Framework

Supported in: 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

Windows 7, Windows Vista SP1 or later, Windows XP SP3, Windows XP SP2 x64 Edition, Windows Server 2008 (Server Core not supported), Windows Server 2008 R2 (Server Core supported with SP1 or later), Windows Server 2003 SP2

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.

Date

History

Reason

March 2011

Noted that the class uses a modified version of the subtractive random number generator algorithm, and added the Notes to Callers section.

Content bug fix.

Did you find this helpful?
(2000 characters remaining)
Community Content Add
Annotations FAQ
Avoid thread safety problems with Random type
This article  http://blog.codeeffects.com/Article/Generate-Random-Numbers-And-Strings-C-Sharp  contains a simple solution of how to generate a different seed for the Random c-tor at any time. That makes possible to create a new local instance of Random on each call. And that eliminates the need for a global instance of Random and for locks of "semaphore" objects. Hope this helps.
Random is not Thread Safe
There is a very nasty side effect that can happen when the same Random object is used by multiple threads: it just stops working (i.e. there is a race condition which when triggered, the return value from the 'random.Next....' methods will be 0 (for all subsequent calls))

This means that one has to be careful when using the Random Class.

Here are two blog posts with more details, comments and code samples on this topic:

The Random Class and Thread Safety

This lack of thread safety is documented in the Thread Safety section of this topic. For more information about how to call Random instance methods safely from multiple threads, see the "Random Instance Methods and Thread Safety" section of the following post.

--Ron Petrusha
Common Language Runtime User Education
Microsoft Corporation

Non thread safe, returns all zeros

Although the documentation says "Any instance members are not guaranteed to be thread safe.", the failure case of using a single Random instance from multiple threads is severe enough that I think it deserves special mention.

If the Random class is accessed from multiple threads at the same time, the random number generator will break, and Random.Next() will return all zeros, forever. If you're doing anything with multiple threads, be very sure that you're not accessing a single Random object simultaneously from multiple threads

Random Instance Methods and Thread Safety

This limitation, as you point out, is already documented in the Thread Safety section of this topic. If the members of a type are not guaranteed to be thread-safe, simultaneous or near-simultaneous calls to the members of an instance of the type created on one thread from other threads are likely to produce unexpected or erroneous results. And as you also point out, developers should ""be very sure that you're not accessing a single Random object simultaneously from multiple threads". It's important to emphasize, though, that this does not mean that calls to instance methods that are not thread-safe should not be made from multiple threads. Instead, you can safely call instance methods from multiple threads as long as you ensure that only a single thread can make the call at any particular time. There are a variety of ways to do this by using the synchronization types in the System.Threading namespace, or by using language constructs such as lock in C# and SyncLock in Visual Basic.

For example, the following example illustrates the problem. A main thread and ten additional threads each try to retrieve two million random numbers. A relatively small number of the potential twelve million calls are executed before the random number generator fails.

using System;
using System.Threading;
public class Example
{
[ThreadStatic] static double previous = 0.0;
[ThreadStatic] static bool abnormal;
[ThreadStatic] static int perThreadCtr = 0;

Random rand;

public Example()
{
rand = new Random();
}
public static void Main()
{
Example ex = new Example();
Thread.CurrentThread.Name = "Main";
ex.Execute();
Console.WriteLine("Program execution concluded...");
}
private void Execute()
{
for (int threads = 1; threads <= 10; threads++)
{
Thread newThread = new Thread(new ThreadStart(this.GetRandomNumbers));
newThread.Name = threads.ToString();
newThread.Start();
}
this.GetRandomNumbers();
}
private void GetRandomNumbers()
{
double result = 0.0;

for (int ctr = 0; ctr < 2000000; ctr++)
{
result = rand.NextDouble();
if (result == previous) {
abnormal = true;
break;
}
else {
previous = result;
}
perThreadCtr++;
}

// get last result
if (abnormal)
Console.WriteLine("Result is {0} in Thread {1}", previous, Thread.CurrentThread.Name);

Console.WriteLine("Thread {0} finished execution of {1:N0} iterations.",
Thread.CurrentThread.Name, perThreadCtr);
}
}

By using the C# lock statement, as in the following example, we can ensure the thread safety of our application, and also ensure that each thread retrieves two million random numbers.

using System;
using System.Threading;

public class Example
{
[ThreadStatic] static double previous = 0.0;
[ThreadStatic] static bool abnormal;
[ThreadStatic] static int perThreadCtr = 0;
[ThreadStatic] static int ctr = 0;

private static Object lockObj;
Random rand;

public Example()
{
rand = new Random();
lockObj = new Object();
}
public static void Main()
{
Example ex = new Example();
Thread.CurrentThread.Name = "Main";
ex.Execute();
Console.WriteLine("Program execution concluded...");
}
private void Execute()
{
for (int threads = 1; threads <= 10; threads++)
{
Thread newThread = new Thread(new ThreadStart(this.GetRandomNumbers));
newThread.Name = threads.ToString();
newThread.Start();
}
this.GetRandomNumbers();
}
private void GetRandomNumbers()
{
double result = 0.0;


for (ctr = 0; ctr < 2000000; ctr++)
{
lock (lockObj) {
result = rand.NextDouble();
}
if (result == previous) {
abnormal = true;
break;
}
else {
previous = result;
}
perThreadCtr++;
}
// get last result
if (abnormal)
Console.WriteLine("Result is {0} in Thread {1}", previous, Thread.CurrentThread.Name);

Console.WriteLine("Thread {0} finished execution of {1:N0} iterations.",
Thread.CurrentThread.Name, perThreadCtr);
}
}


--Ron Petrusha
Common Language Runtime User Education
Microsoft Corporation

Error in generating Random Number
I have created a windows application and had taken a label to show the display. In the form load I have written the code below. When I debug I get random numbers but when I run without debug the same number repeats over and again. Why this happens? Seems to be a bug?

StringBuilder strRandom = new StringBuilder("");

for (int i = 0; i &lt;10; i++)

{

Random Rnd = new Random();

int Rand = Rnd.Next(20);

strRandom = strRandom.Append(Rand.ToString() + "," + System.Environment.NewLine);

Rnd = null;

}

Lbl.Text = strRandom.ToString();

Random Produces Pseudo-Random Numbers


The exact sequence of random numbers generated by the Random class depends on the seed value with which the random number generator is instantiated. Given identical seed values, instances of the Random class will generate identical sequences of random numbers.

In the case of this example, the parameterless constructor instantiates a Random instance with a seed value based on the system clock. Given the speed with which the for loop in this example executes, the practical effect is that each instance of Random is passed the same seed value. As a result, the same sequence of random numbers is generated. This is mentioned in the documentation at http://msdn.microsoft.com/en-us/library/system.random.aspx: "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 documentation for the default constructor at http://msdn.microsoft.com/en-us/library/h343ddh9.aspx contains more detail: "The default seed value is derived from the system clock and has finite resolution. As a result, different Random objects that are created in close succession by a call to the default constructor will have identical default seed values and, therefore, will produce identical sets of random numbers. This problem can be avoided by using a single Random object to generate all random numbers. You can also work around it by modifying the seed value returned by the system clock and then explicitly providing this new seed value to the Random(Int32) constructor."

In the case of this example, instantiating a single Random object outside of the for loop solves the problem:

      StringBuilder strRandom = new StringBuilder("");
Random Rnd = new Random();
for (int i = 0; i <10; i++)
{
int Rand = Rnd.Next(20);
strRandom = strRandom.Append(Rand.ToString() + "," + System.Environment.NewLine);
}
Console.WriteLine(strRandom.ToString());


I hope that this helps.

--Ron Petrusha
Common Language Runtime Developer Content
Microsoft Corporation


F# and Random example
  open System
// The MAIN in F#
[<STAThread>]
[<EntryPoint>]
let main (args) =
    let urandom = new Random()
    match args with
    | _ ->
// this will sleep for a random time multiplied by 10...
    System.Threading.Thread.Sleep(10 * urandom.Next());
    0
Random.Next never get to the max value

I'm studing the Random numbers generation and I never get the max value of my random.Next when setting the minValue and maxValue.

Here's the code I'm using:


Dim rnd As New Random

For i = 0 To 1500000
Dim num = rnd.Next(1, 9)

If num = 9 Then
MsgBox("i=" &amp; i &amp; " - num=" &amp; num)
End If
Next

This code loops 1,500,000 times generating a random number between 1 and 9 and never gets 9 as the generated number.

If I set rnd.Next(1,10) I can get 9 before the 10th loop...

Is there any rule I missed about the ".Next" method used with minValue and maxValue does return the "maxValue" at all? (or should I just use "maxValue +1" to get the maximum value returned from this function?)

Regards,
Victor

Why Random.Next Never Returns the Maximum Value


The behavior that you're describing is documented and is by design. According to the documentation, the maxValue parameter in the Random.Next(Int32, Int32) method represents "the exclusive upper bound of the random number returned." "Exclusive" means that that value is not part of the set. In other words, the second integer parameter represents the first integer that is outside the range of the values returned by the method.

Actually, there are three overloads of Random.Next, and each behaves in this way. The parameterless overload returns an integer that is greater than or equal to zero and less than Int32.MaxValue. Random.Next(Int32) returns an integer that ranges from zero to one less than its parameter. And Random.Next(Int32, Int32) returns an integer that ranges from the value of its first parameter to one less than the value of its second parameter.


--Ron Petrusha
Common Language Runtime Developer Content
Microsoft Corporation

RandomGenerator to dynamically generate boolean, integer, byte, double, string, datetime
I created RandomGenerator class in my tool suit so that any of the random types can very easily be generated here is the code:


public static class RandomGenerator
{
    private static readonly Random random = new Random(); 

    private static readonly object syncLock = new object(); 

    public static bool GetBoolean()
    {
        lock (syncLock)
        {
            return (random.Next(2) == 1);
        }
    }

    public static int GetInteger(int MaxValue)
    {
        lock (syncLock)
        {
            return random.Next(0, MaxValue);
        }
    }

    public static byte GetByte()
    {
        return ((byte)GetInteger(256));
    }

    public static string GetUppercaseAlphabetString(int size)
    {
        StringBuilder builder = new StringBuilder();
        char ch;
        for (int i = 0; i < size; i++)
        {
            ch = Convert.ToChar(65 + GetInteger(27));
            builder.Append(ch);
        }
        return builder.ToString();
    }

    public static DateTime GetDateBetween1995andNow()
    {
        DateTime start = new DateTime(1995, 1, 1); 
        int range = ((TimeSpan)(DateTime.Today - start)).Days;
        return start.AddDays(GetInteger(range));
    }

    public static double GetDouble()
    {
        lock (syncLock)
        {
            return random.NextDouble();
        }
    }
}
Bug in System.Random (not using (24, 55) lagged fibonacci)
I investigated the System.Random implementation.    The reference cites Knuth 1981 book (actually p. 171-172) used the subtractive lagged Fibonacci generator of (24, 55) which gurantees the period to be at least 2^55 -1.  Unfortunately .NET Reflector shows that the last three lines of Random(int Seed) has this.inext = 0; this.inextp = 21; .   The "21" should be "31" ( =55-24).   Thus the current implementation has no guarantee on the period at all.   The implementation is very similar to Numerical Recipes Ran3 routine (rather than Knuth original) and you would have detected the value 21 is wrong.    Can someone at Microsoft comment on this?    Did this "wrong" generator pass suites of tests like DieHard?