Este artículo se tradujo automáticamente. Para ver el artículo en inglés, active la casilla Inglés. Además, puede mostrar el texto en inglés en una ventana emergente si mueve el puntero del mouse sobre el texto.
Traducción
Inglés

Clase Random

 

Publicado: noviembre de 2016

Representa un generador de números seudoaleatorios, que es un dispositivo que genera una secuencia de números que cumplen determinados requisitos estadísticos de aleatoriedad.

Para examinar el código fuente de .NET Framework para este tipo, vea la Reference Source.

Espacio de nombres:   System
Ensamblado:  mscorlib (en mscorlib.dll)


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

NombreDescripción
System_CAPS_pubmethodRandom()

Inicializa una nueva instancia de la Random clase, con un valor de inicialización predeterminado que depende del tiempo.

System_CAPS_pubmethodRandom(Int32)

Inicializa una nueva instancia de la Random clase, utilizando el valor de inicialización especificado.

NombreDescripción
System_CAPS_pubmethodEquals(Object)

Determina si el objeto especificado es igual al objeto actual.(Heredado de Object).

System_CAPS_protmethodFinalize()

Permite que un objeto intente liberar recursos y realizar otras operaciones de limpieza antes de que sea reclamado por la recolección de elementos no utilizados.(Heredado de Object).

System_CAPS_pubmethodGetHashCode()

Sirve como la función hash predeterminada.(Heredado de Object).

System_CAPS_pubmethodGetType()

Obtiene el Type de la instancia actual.(Heredado de Object).

System_CAPS_protmethodMemberwiseClone()

Crea una copia superficial del Object actual.(Heredado de Object).

System_CAPS_pubmethodNext()

Devuelve un entero aleatorio no negativo.

System_CAPS_pubmethodNext(Int32)

Devuelve un entero aleatorio no negativo que es menor que el valor máximo especificado.

System_CAPS_pubmethodNext(Int32, Int32)

Devuelve un entero aleatorio que está dentro de un intervalo especificado.

System_CAPS_pubmethodNextBytes(Byte[])

Rellena con números aleatorios los elementos de una matriz de bytes especificada.

System_CAPS_pubmethodNextDouble()

Devuelve un número de punto flotante aleatorio que es mayor o igual que 0,0 y menor que 1,0.

System_CAPS_protmethodSample()

Devuelve un número de punto flotante aleatorio entre 0,0 y 1,0.

System_CAPS_pubmethodToString()

Devuelve una cadena que representa el objeto actual.(Heredado de Object).

System_CAPS_noteNota

Para ver el código fuente de .NET Framework para este tipo, consulte el Reference Source. Puede examinar el código fuente en línea, descargue la referencia para verla sin conexión y recorrer (incluidas las revisiones y actualizaciones) durante la depuración; see instructions.

Números pseudoaleatorios se eligen con la misma probabilidad en un conjunto finito de números. Los números elegidos no son completamente aleatorios porque se utiliza un algoritmo matemático para seleccionarlos, pero su aleatoriedad es suficiente para fines prácticos. La implementación actual de la Random clase se basa en una versión modificada de sustracción generador algoritmo de números aleatorios de Knuth. Para obtener más información, consulte E. D. Knuth. El arte de la programación, volumen 2: algoritmos Seminumerical. Addison-Wesley, Reading, MA, tercera edición, 1997.

Para generar un número aleatorio criptográficamente seguro, como uno que es adecuado para crear una contraseña aleatoria, use la RNGCryptoServiceProvider clase o derivar una clase de System.Security.Cryptography.RandomNumberGenerator.

En este tema:

Crear una instancia de generador de números aleatorios
evitar varias creaciones de instancias
System.Random la seguridad de clase y el subproceso
generar diferentes tipos de números aleatorios
sustituyendo su propio algoritmo
¿cómo usa System.Random para...
Recuperar la misma secuencia de valores aleatorios
recuperar secuencias únicas de valores aleatorios
recuperar enteros en un intervalo especificado
recuperar enteros con un número especificado de dígitos
recuperar valores de punto flotante en un intervalo especificado
generar valores booleanos aleatorios
generar enteros de 64 bits aleatorios
recuperar bytes en un intervalo especificado
recuperar un elemento de una matriz o colección aleatoriamente
recuperar un elemento único de una matriz o colección

Crear instancias del generador de números aleatorios proporcionando un valor de inicialización (un valor inicial para el algoritmo de generación de números pseudoaleatorios) a un Random constructor de clase. Puede proporcionar el valor de inicialización explícita o implícitamente:

  • El Random(Int32) constructor utiliza un valor de inicialización explícita que proporcione.

  • El Random() constructor utiliza el reloj del sistema para proporcionar un valor de inicialización. Se trata de la manera más común de una instancia de generador de números aleatorios.

Si se usa el mismo valor de inicialización para independiente Random objetos, generarán la misma serie de números aleatorios. Esto puede ser útil para crear un conjunto de pruebas que procesa los valores aleatorios o para reproducir juegos que derivan sus datos de números aleatorios. Sin embargo, tenga en cuenta que Random objetos en los procesos que se ejecutan con las distintas versiones de .NET Framework pueden devolver otra serie de números aleatorios, incluso si se crea una instancia con los valores de inicialización idénticos.

Para generar diferentes secuencias de números aleatorios, hacer el valor de inicialización dependa del tiempo, con lo que se genere una serie diferente con cada nueva instancia de Random. Parametrizado Random(Int32) constructor puede tomar un Int32 valor en función del número de pasos en la hora actual, mientras que sin parámetros Random() constructor utiliza el reloj del sistema para generar su valor de inicialización. Sin embargo, como el reloj tiene una resolución finita, utilizando el constructor sin parámetros para crear diferentes Random objetos en estrecha sucesión crea generadores de números aleatorios que generan secuencias idénticas de números aleatorios. En el ejemplo siguiente se muestra cómo dos Random objetos que se crean instancias en estrecha sucesión generan una serie idéntica de números aleatorios. En la mayoría de los sistemas Windows Random objetos creados dentro de 15 milisegundos de otra están probable que tengan valores de inicialización idénticos.

using System;

public class Class1
{
   public static void Main()
   {
      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 output like the following:
//       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        

Para evitar este problema, cree un único Random objeto en lugar de varios objetos.

Inicializar dos generadores de números aleatorios en un bucle ajustado, o en una sucesión rápida crea dos generadores de números aleatorios que pueden generar secuencias idénticas de números aleatorios. En la mayoría de los casos, esto no es la intención del programador y puede provocar problemas de rendimiento, ya que crear instancias e inicializar un generador de números aleatorios son un proceso relativamente costoso.

Para mejorar el rendimiento tanto para evitar crear accidentalmente independientes generadores de números aleatorios que generan secuencias numéricas idénticas, se recomienda crear uno Random objeto para generar muchos números aleatorios con el tiempo, en lugar de crear nuevos Random objetos para generar un número aleatorio.

Sin embargo, la Random clase no es seguro para subprocesos. Si se llama a Random métodos desde varios subprocesos, siga las instrucciones que se describen en la sección siguiente.

En lugar de crear instancias individuales Random objetos, se recomienda que cree una sola Random instancia para generar todos los números aleatorios necesarios para la aplicación. Sin embargo, Random objetos no son seguros para subprocesos. Si su aplicación llama Random métodos desde varios subprocesos, debe utilizar un objeto de sincronización para asegurarse de que sólo un subproceso puede tener acceso a un generador de números aleatorios a la vez. Si no está seguro de que el Random se tiene acceso a objetos de una manera segura para subprocesos, las llamadas a métodos que devuelven números aleatorios devuelven 0.

En el ejemplo siguiente se usa C# lock (instrucción) y Visual Basic SyncLock (instrucción) para asegurarse de que un único generador de números aleatorios se tiene acceso mediante 11 subprocesos de una manera segura para subprocesos. Cada subproceso genera números aleatorios de 2 millones, cuenta el número de números aleatorios generados y calcula su suma y, a continuación, actualiza los totales de todos los subprocesos cuando finaliza la ejecución.

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();
      source.Dispose();

      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

En el ejemplo se garantiza la seguridad para subprocesos de las maneras siguientes:

  • El ThreadStaticAttribute atributo se utiliza para definir variables locales de subproceso que realizan el seguimiento del número total de números aleatorios generados y su suma para cada subproceso.

  • Un bloqueo (el lock instrucción en C# y el SyncLock instrucción en Visual Basic) protege el acceso a las variables para el recuento total y la suma de todos los números aleatorios generados en todos los subprocesos.

  • Un semáforo (la CountdownEvent objeto) se utiliza para garantizar que el subproceso principal se bloquea hasta que todos los demás subprocesos complete la ejecución.

  • En el ejemplo se comprueba si el generador de números aleatorios están dañado al determinar si dos llamadas consecutivas para métodos de generación de números aleatorios devuelven 0. Si se detectan daños, el ejemplo utiliza la CancellationTokenSource objeto para indicar que se deben cancelar todos los subprocesos.

  • Antes de generar cada número aleatorio, cada subproceso comprueba el estado de la CancellationToken objeto. Si se solicita la cancelación, el ejemplo llama el CancellationToken.ThrowIfCancellationRequested método para cancelar el subproceso.

El ejemplo siguiente es idéntico al primero, salvo que usa un Task objeto y una expresión lambda en lugar de Thread objetos.

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);
         }         
      }
      finally {
         source.Dispose();
      }
   }
}
// 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

Se diferencia del primer ejemplo de las maneras siguientes:

  • Las variables que se va a realizar un seguimiento de la cantidad de números aleatorios generados y la suma de cada tarea son locales a la tarea, por lo que no es necesario utilizar el ThreadStaticAttribute atributo.

  • Estático Task.WaitAll método se utiliza para garantizar que el subproceso principal no se completa antes de que han terminado de todas las tareas. No es necesario para la CountdownEvent objeto.

  • La excepción que es el resultado de la cancelación de la tarea aparece en la Task.WaitAll (método). En el ejemplo anterior, se controla por cada subproceso.

El generador de números aleatorios proporciona métodos que permiten generar los siguientes tipos de números aleatorios:

  • Una serie de Byte valores. Determinar el número de valores de byte pasando una matriz que se inicializa en el número de elementos que desea que el método para volver a la NextBytes (método). El ejemplo siguiente genera 20 bytes.

    using System;
    
    public class Example
    {
       public static void Main()
       {
          Random rnd = new Random();
          Byte[] bytes = new Byte[20];
          rnd.NextBytes(bytes);  
          for (int ctr = 1; ctr <= bytes.Length; ctr++) {
             Console.Write("{0,3}   ", bytes[ctr - 1]);
             if (ctr % 10 == 0) Console.WriteLine();
          } 
       }
    }
    // The example displays output like the following:
    //       141    48   189    66   134   212   211    71   161    56
    //       181   166   220   133     9   252   222    57    62    62
    
  • Un entero único. Puede elegir si desea que un entero entre 0 y un valor máximo (Int32.MaxValue – 1) llamando a la Next() (método), un número entero entre 0 y un valor específico mediante una llamada a la Next(Int32) (método), o un número entero dentro de un intervalo de valores mediante una llamada a la Next(Int32, Int32) (método). En las sobrecargas con parámetros, el valor máximo especificado es exclusivo; es decir, el número máximo real generado uno menor que el valor especificado.

    El ejemplo siguiente se llama el Next(Int32, Int32) método para generar 10 números aleatorios entre -10 y 10. Tenga en cuenta que el segundo argumento del método especifica el límite superior exclusivo del intervalo de valores aleatorios devuelto por el método. En otras palabras, el entero más grande que el método puede devolver uno es menor que este valor.

    using System;
    
    public class Example
    {
       public static void Main()
       {
          Random rnd = new Random();
          for (int ctr = 0; ctr < 10; ctr++) {
             Console.Write("{0,3}   ", rnd.Next(-10, 11));
          }
       }
    }
    // The example displays output like the following:
    //    2     9    -3     2     4    -7    -3    -8    -8     5
    
  • Un único valor punto flotante entre 0,0 y menor que 1,0 llamando el NextDouble método. Límite superior exclusivo del número aleatorio devuelto por el método es 1, por lo que su límite superior real es 0.99999999999999978. El ejemplo siguiente genera 10 números de punto flotante aleatorios.

    using System;
    
    public class Example
    {
       public static void Main()
       {
          Random rnd = new Random();
          for (int ctr = 0; ctr < 10; ctr++) {
             Console.Write("{0,-19:R}   ", rnd.NextDouble());
             if ((ctr + 1) % 3 == 0) Console.WriteLine();
          }
       }
    }
    // The example displays output like the following:
    //    0.7911680553998649    0.0903414949264105    0.79776258291572455    
    //    0.615568345233597     0.652644504165577     0.84023809378977776   
    //    0.099662564741290441   0.91341467383942321  0.96018602045261581   
    //    0.74772306473354022
    
System_CAPS_importantImportante

El Next(Int32, Int32) método le permite especificar el intervalo del número aleatorio devuelto. Sin embargo, la maxValue parámetro, que especifica el intervalo superior devuelve números, es exclusivo, no un inclusivo valor. Esto significa que la llamada al método Next(0, 100) devuelve un valor entre 0 y 99 y no está comprendido entre 0 y 100.

También puede utilizar el Random clase para tareas como la generación de valores Boolean aleatorios, generar los valores de punto flotante aleatorio con un intervalo de 0 a 1, generar enteros de 64 bits aleatorios, y aleatoriamente recuperar un único elemento de una matriz o colección. Para responder a estas y otras tareas comunes, consulte la ¿cómo usa System.Random para... sección.

Puede implementar su propio generador de números aleatorios mediante la herencia de la Random clase y suministrar su algoritmo de generación de números aleatorios. Para proporcionar su propio algoritmo, debe invalidar el Sample método, que implementa el algoritmo de generación de números aleatorios. También debe reemplazar el Next(), Next(Int32, Int32), y NextBytes métodos para asegurarse de que llame a su Sample método. No es necesario reemplazar el Next(Int32) y NextDouble métodos.

Para obtener un ejemplo que se deriva de la Random clase y modifica su generador de números pseudoaleatorios de forma predeterminada, consulte la Sample página de referencia.

Las siguientes secciones se describen y proporcionan código de ejemplo para algunas de las formas que desea usar números aleatorios en la aplicación.

A veces desea generar la misma secuencia de números aleatorios en escenarios de prueba de software y juegos. Pruebas con la misma secuencia de números aleatorios permite detectar regresiones y confirmar correcciones de errores. Mediante la misma secuencia de número aleatorio en juegos le permite reproducir juegos anteriores.

Puede generar la misma secuencia de números aleatorios que proporciona el mismo valor de inicialización para el Random(Int32) constructor. El valor de inicialización, proporciona un valor inicial para el algoritmo de generación de números pseudoaleatorios. En el ejemplo siguiente se utiliza 100100 como un valor de inicialización arbitrario para crear instancias de la Random objeto, muestra los valores de punto flotante aleatorios 20 y conserva el valor de inicialización. A continuación, restaura el valor de inicialización, crea un nuevo generador de números aleatorios y muestra los mismos valores de punto flotante aleatorios 20. Tenga en cuenta que el ejemplo puede producir diferentes secuencias de números aleatorios si se ejecutan en diferentes versiones de .NET Framework.

using System;
using System.IO;

public class Example
{
   public static void Main()
   {
      int seed = 100100;
      ShowRandomNumbers(seed);
      Console.WriteLine();

      PersistSeed(seed);

      DisplayNewRandomNumbers(); 
   }

   private static void ShowRandomNumbers(int seed)
   {
      Random rnd = new Random(seed);
      for (int ctr = 0; ctr <= 20; ctr++)
         Console.WriteLine(rnd.NextDouble());
   }

   private static void PersistSeed(int seed)
   {
      FileStream fs = new FileStream(@".\seed.dat", FileMode.Create);
      BinaryWriter bin = new BinaryWriter(fs);
      bin.Write(seed);
      bin.Close();
   }

   private static void DisplayNewRandomNumbers()
   {
      FileStream fs = new FileStream(@".\seed.dat", FileMode.Open);
      BinaryReader bin = new BinaryReader(fs);
      int seed = bin.ReadInt32();
      bin.Close();

      Random rnd = new Random(seed);
      for (int ctr = 0; ctr <= 20; ctr++)
         Console.WriteLine(rnd.NextDouble());
   }
}
// The example displays output like the following:
//       0.500193602172748
//       0.0209461245783354
//       0.465869495396442
//       0.195512794514891
//       0.928583675496552
//       0.729333720509584
//       0.381455668891527
//       0.0508996467343064
//       0.019261200921266
//       0.258578445417145
//       0.0177532266908107
//       0.983277184415272
//       0.483650274334313
//       0.0219647376900375
//       0.165910115077118
//       0.572085966622497
//       0.805291457942357
//       0.927985211335116
//       0.4228545699375
//       0.523320379910674
//       0.157783938645285
//       
//       0.500193602172748
//       0.0209461245783354
//       0.465869495396442
//       0.195512794514891
//       0.928583675496552
//       0.729333720509584
//       0.381455668891527
//       0.0508996467343064
//       0.019261200921266
//       0.258578445417145
//       0.0177532266908107
//       0.983277184415272
//       0.483650274334313
//       0.0219647376900375
//       0.165910115077118
//       0.572085966622497
//       0.805291457942357
//       0.927985211335116
//       0.4228545699375
//       0.523320379910674
//       0.157783938645285

Proporcionar valores de inicialización distintos para instancias de la Random clase hace que cada generador de números aleatorios generar una secuencia de valores diferentes. Puede proporcionar un valor de inicialización explícitamente llamando el Random(Int32) constructor, o implícitamente, mediante una llamada a la Random() constructor. La mayoría de los desarrolladores llaman al constructor sin parámetros, que utiliza el reloj del sistema. En el ejemplo siguiente se utiliza este enfoque para crear dos instancias de Random instancias. Cada instancia muestra una serie de 10 números enteros aleatorios.

using System;
using System.Threading;

public class Example
{
   public static void Main()
   {
      Console.WriteLine("Instantiating two random number generators...");
      Random rnd1 = new Random();
      Thread.Sleep(2000);
      Random rnd2 = new Random();

      Console.WriteLine("\nThe first random number generator:");
      for (int ctr = 1; ctr <= 10; ctr++)
         Console.WriteLine("   {0}", rnd1.Next());

      Console.WriteLine("\nThe second random number generator:");
      for (int ctr = 1; ctr <= 10; ctr++)
         Console.WriteLine("   {0}", rnd2.Next());
   }
}
// The example displays output like the following:
//       Instantiating two random number generators...
//       
//       The first random number generator:
//          643164361
//          1606571630
//          1725607587
//          2138048432
//          496874898
//          1969147632
//          2034533749
//          1840964542
//          412380298
//          47518930
//       
//       The second random number generator:
//          1251659083
//          1514185439
//          1465798544
//          517841554
//          1821920222
//          195154223
//          1538948391
//          1548375095
//          546062716
//          897797880

Sin embargo, debido a su resolución finita, el reloj del sistema no detecta las diferencias horarias que son menos de aproximadamente 15 milisegundos. Por lo tanto, si el código llama a la Random() sobrecarga al crear instancias de dos Random objetos en sucesión, que sin darse cuenta pueden proporcionar los objetos con valores de inicialización idénticos. Para ver esto en el ejemplo anterior, convierta en comentario la Thread.Sleep llamada al método y compilación y vuelva a ejecutar el ejemplo.

Para evitar que esto suceda, se recomienda que cree una instancia de una sola Random objeto en lugar de varias. Sin embargo, puesto que Random no subprocesos seguros, debe usar algún dispositivo de sincronización si tiene acceso a una Random la instancia desde varios subprocesos; para obtener más información, consulte aleatorio de la seguridad de clase y el subproceso anteriormente en este tema. Como alternativa, puede usar un mecanismo de retardo, como el Sleep método utilizado en el ejemplo anterior, para asegurarse de que la creación de instancias produzca distancia de más de 15 milisegundos.

Enteros en un intervalo especificado se pueden recuperar llamando el Next(Int32, Int32) método, que le permite especificar el inferior y el límite superior de los números que desea que el generador de números aleatorios para devolver. El límite superior es exclusivo, no un inclusivo valor. Es decir, no se incluye, en el intervalo de valores devueltos por el método. En el ejemplo siguiente se utiliza este método para generar enteros aleatorios entre -10 y 10. Tenga en cuenta que especifica 11, que es una unidad mayor que el valor deseado, como el valor de la maxValue argumento en la llamada al método.

using System;

public class Example
{
   public static void Main()
   {
      Random rnd = new Random();
      for (int ctr = 1; ctr <= 15; ctr++) {
         Console.Write("{0,3}    ", rnd.Next(-10, 11));
         if(ctr % 5 == 0) Console.WriteLine();
      }   
   }
}
// The example displays output like the following:
//        -2     -5     -1     -2     10
//        -3      6     -4     -8      3
//        -7     10      5     -2      4

Puede llamar a la Next(Int32, Int32) método para recuperar los números con un número especificado de dígitos. Por ejemplo, para recuperar los números con cuatro dígitos (es decir, los números comprendidos entre 1000 y 9999), se llama a la Next(Int32, Int32) método con un minValue valor de 1000 y un maxValue valor de 10000, como se muestra en el ejemplo siguiente.

using System;

public class Example
{
   public static void Main()
   {
      Random rnd = new Random();
      for (int ctr = 1; ctr <= 50; ctr++) {
         Console.Write("{0,3}    ", rnd.Next(1000, 10000));
         if(ctr % 10 == 0) Console.WriteLine();
      }   
   }
}
// The example displays output like the following:
//    9570    8979    5770    1606    3818    4735    8495    7196    7070    2313
//    5279    6577    5104    5734    4227    3373    7376    6007    8193    5540
//    7558    3934    3819    7392    1113    7191    6947    4963    9179    7907
//    3391    6667    7269    1838    7317    1981    5154    7377    3297    5320
//    9869    8694    2684    4949    2999    3019    2357    5211    9604    2593

El NextDouble método devuelve los valores de punto flotante aleatorios ese intervalo entre 0 y menor que 1. Sin embargo, a menudo deseará generar valores aleatorios en algún otro intervalo.

Si el intervalo entre los valores mínimos y máximo deseados es 1, puede agregar la diferencia entre el intervalo inicio deseado y 0 para el número devuelto por la NextDouble (método). En el ejemplo siguiente se hace esto para generar 10 números aleatorios entre -1 y 0.

using System;

public class Example
{
   public static void Main()
   {
      Random rnd = new Random();
      for (int ctr = 1; ctr <= 10; ctr++)
         Console.WriteLine(rnd.NextDouble() - 1);
   }
}
// The example displays output like the following:
//       -0.930412760437658
//       -0.164699016215605
//       -0.9851692803135
//       -0.43468508843085
//       -0.177202483255976
//       -0.776813320245972
//       -0.0713201854710096
//       -0.0912875561468711
//       -0.540621722368813
//       -0.232211863730201

Para generar los números de punto flotante aleatorios cuyo límite inferior es 0 pero límite superior es mayor que 1 (o, en el caso de números negativos, cuyo límite inferior es menor que -1 y límite superior es 0), multiplique el número aleatorio por el límite distinto de cero. En el ejemplo siguiente se hace esto para generar números de punto flotante aleatorios de 20 millones de ese intervalo de 0 a Int64.MaxValue. En también muestra la distribución de los valores aleatorios generados por el método.

using System;

public class Example
{
   public static void Main()
   {
      const long ONE_TENTH = 922337203685477581;

      Random rnd = new Random();
      double number;
      int[] count = new int[10];

      // Generate 20 million integer values between.
      for (int ctr = 1; ctr <= 20000000; ctr++) {
         number = rnd.NextDouble() * Int64.MaxValue;
         // Categorize random numbers into 10 groups.
         count[(int) (number / ONE_TENTH)]++;
      }
      // Display breakdown by range.
      Console.WriteLine("{0,28} {1,32}   {2,7}\n", "Range", "Count", "Pct.");
      for (int ctr = 0; ctr <= 9; ctr++)
         Console.WriteLine("{0,25:N0}-{1,25:N0}  {2,8:N0}   {3,7:P2}", ctr * ONE_TENTH,
                            ctr < 9 ? ctr * ONE_TENTH + ONE_TENTH - 1 : Int64.MaxValue, 
                            count[ctr], count[ctr]/20000000.0);
   }
}
// The example displays output like the following:
//                           Range                            Count      Pct.
//    
//                            0-  922,337,203,685,477,580  1,996,148    9.98 %
//      922,337,203,685,477,581-1,844,674,407,370,955,161  2,000,293   10.00 %
//    1,844,674,407,370,955,162-2,767,011,611,056,432,742  2,000,094   10.00 %
//    2,767,011,611,056,432,743-3,689,348,814,741,910,323  2,000,159   10.00 %
//    3,689,348,814,741,910,324-4,611,686,018,427,387,904  1,999,552   10.00 %
//    4,611,686,018,427,387,905-5,534,023,222,112,865,485  1,998,248    9.99 %
//    5,534,023,222,112,865,486-6,456,360,425,798,343,066  2,000,696   10.00 %
//    6,456,360,425,798,343,067-7,378,697,629,483,820,647  2,001,637   10.01 %
//    7,378,697,629,483,820,648-8,301,034,833,169,298,228  2,002,870   10.01 %
//    8,301,034,833,169,298,229-9,223,372,036,854,775,807  2,000,303   10.00 %

Para generar los números de punto flotante aleatorios entre dos valores arbitrarios, como el Next(Int32, Int32) método no para números enteros, use la siguiente fórmula:

Random.NextDouble() * (maxValue – minValue) + minValue

En el ejemplo siguiente se genera números aleatorios de 1 millón que van desde 10.0 a 11.0 y muestra su distribución.

using System;

public class Example
{
   public static void Main()
   {
      Random rnd = new Random();
      int lowerBound = 10;
      int upperBound = 11;
      int[] range = new int[10];
      for (int ctr = 1; ctr <= 1000000; ctr++) {
         Double value = rnd.NextDouble() * (upperBound - lowerBound) + lowerBound;
         range[(int) Math.Truncate((value - lowerBound) * 10)]++; 
      }

      for (int ctr = 0; ctr <= 9; ctr++) {
         Double lowerRange = 10 + ctr * .1;
         Console.WriteLine("{0:N1} to {1:N1}: {2,8:N0}  ({3,7:P2})", 
                           lowerRange, lowerRange + .1, range[ctr], 
                           range[ctr] / 1000000.0);
      } 
   }
}
// The example displays output like the following:
//       10.0 to 10.1:   99,929  ( 9.99 %)
//       10.1 to 10.2:  100,189  (10.02 %)
//       10.2 to 10.3:   99,384  ( 9.94 %)
//       10.3 to 10.4:  100,240  (10.02 %)
//       10.4 to 10.5:   99,397  ( 9.94 %)
//       10.5 to 10.6:  100,580  (10.06 %)
//       10.6 to 10.7:  100,293  (10.03 %)
//       10.7 to 10.8:  100,135  (10.01 %)
//       10.8 to 10.9:   99,905  ( 9.99 %)
//       10.9 to 11.0:   99,948  ( 9.99 %)

La Random clase no proporciona métodos que generan Boolean valores. Sin embargo, puede definir su propia clase o método para hacerlo. En el ejemplo siguiente se define una clase, BooleanGenerator, con un único método, NextBoolean. La BooleanGenerator clase almacena una Random objeto como una variable privada. El NextBoolean llamadas al método el Random.Next(Int32, Int32) método y pasa el resultado a la Convert.ToBoolean(Int32) (método). Tenga en cuenta que 2 se usa como argumento para especificar el límite superior del número aleatorio. Puesto que es un valor exclusivo, la llamada al método devuelve 0 o 1.

using System;

public class Example
{
   public static void Main()
   {
      // Instantiate the Boolean generator.
      BooleanGenerator boolGen = new BooleanGenerator();
      int totalTrue = 0, totalFalse = 0;

      // Generate 1,0000 random Booleans, and keep a running total.
      for (int ctr = 0; ctr < 1000000; ctr++) {
          bool value = boolGen.NextBoolean();
          if (value)
             totalTrue++;
          else
             totalFalse++;
      }
      Console.WriteLine("Number of true values:  {0,7:N0} ({1:P3})", 
                        totalTrue, 
                        ((double) totalTrue)/(totalTrue + totalFalse));
      Console.WriteLine("Number of false values: {0,7:N0} ({1:P3})", 
                        totalFalse, 
                        ((double) totalFalse)/(totalTrue + totalFalse));
   }
}

public class BooleanGenerator
{
   Random rnd;

   public BooleanGenerator()
   {
      rnd = new Random();
   }

   public bool NextBoolean()
   {
      return Convert.ToBoolean(rnd.Next(0, 2));
   }
}
// The example displays output like the following:
//       Number of true values:  500,004 (50.000 %)
//       Number of false values: 499,996 (50.000 %)

En lugar de crear una clase independiente para generar aleatorio Boolean valores, en el ejemplo se ha definido simplemente un único método. En ese caso, sin embargo, la Random objeto debe haberse definido como una variable de nivel de clase para evitar crear instancias de un nuevo Random instancia en cada llamada al método. En Visual Basic, la instancia de Random puede definirse como un estático variable en la NextBoolean (método). En el ejemplo siguiente se proporciona una implementación.

using System;

public class Example
{
   private static Random rnd = new Random();

   public static void Main()
   {
      int totalTrue = 0, totalFalse = 0;

      // Generate 1,0000 random Booleans, and keep a running total.
      for (int ctr = 0; ctr < 1000000; ctr++) {
          bool value = NextBoolean();
          if (value)
             totalTrue++;
          else
             totalFalse++;
      }
      Console.WriteLine("Number of true values:  {0,7:N0} ({1:P3})", 
                        totalTrue, 
                        ((double) totalTrue)/(totalTrue + totalFalse));
      Console.WriteLine("Number of false values: {0,7:N0} ({1:P3})", 
                        totalFalse, 
                        ((double) totalFalse)/(totalTrue + totalFalse));
   }

   public static bool NextBoolean()
   {
      return Convert.ToBoolean(rnd.Next(0, 2));
   }
}
// The example displays output like the following:
//       Number of true values:  499,777 (49.978 %)
//       Number of false values: 500,223 (50.022 %)

Las sobrecargas de los Next método devuelven enteros de 32 bits. Sin embargo, en algunos casos, puede trabajar con enteros de 64 bits. Puede hacerlo de la siguiente manera:

  1. Llame a la NextDouble valor de punto de método para recuperar un flotante de precisión doble.

  2. Multiplicar ese valor por Int64.MaxValue.

En el ejemplo siguiente se utiliza esta técnica para generar enteros aleatorios largo de 20 millones y clasifica en 10 grupos de iguales. A continuación, evalúa la distribución de los números aleatorios contando el número de cada grupo de 0 a Int64.MaxValue. Como muestra el resultado del ejemplo, los números se distribuyen más o menos igual a través del intervalo de un entero largo.

using System;

public class Example
{
   public static void Main()
   {
      const long ONE_TENTH = 922337203685477581;

      Random rnd = new Random();
      long number;
      int[] count = new int[10];

      // Generate 20 million long integers.
      for (int ctr = 1; ctr <= 20000000; ctr++) {
         number = (long) (rnd.NextDouble() * Int64.MaxValue);
         // Categorize random numbers.
         count[(int) (number / ONE_TENTH)]++;
      }
      // Display breakdown by range.
      Console.WriteLine("{0,28} {1,32}   {2,7}\n", "Range", "Count", "Pct.");
      for (int ctr = 0; ctr <= 9; ctr++)
         Console.WriteLine("{0,25:N0}-{1,25:N0}  {2,8:N0}   {3,7:P2}", ctr * ONE_TENTH,
                            ctr < 9 ? ctr * ONE_TENTH + ONE_TENTH - 1 : Int64.MaxValue, 
                            count[ctr], count[ctr]/20000000.0);
   }
}
// The example displays output like the following:
//                           Range                            Count      Pct.
//    
//                            0-  922,337,203,685,477,580  1,996,148    9.98 %
//      922,337,203,685,477,581-1,844,674,407,370,955,161  2,000,293   10.00 %
//    1,844,674,407,370,955,162-2,767,011,611,056,432,742  2,000,094   10.00 %
//    2,767,011,611,056,432,743-3,689,348,814,741,910,323  2,000,159   10.00 %
//    3,689,348,814,741,910,324-4,611,686,018,427,387,904  1,999,552   10.00 %
//    4,611,686,018,427,387,905-5,534,023,222,112,865,485  1,998,248    9.99 %
//    5,534,023,222,112,865,486-6,456,360,425,798,343,066  2,000,696   10.00 %
//    6,456,360,425,798,343,067-7,378,697,629,483,820,647  2,001,637   10.01 %
//    7,378,697,629,483,820,648-8,301,034,833,169,298,228  2,002,870   10.01 %
//    8,301,034,833,169,298,229-9,223,372,036,854,775,807  2,000,303   10.00 %

Una técnica alternativa que usa manipulación de bits no genera números aleatorios verdaderos. Esta técnica se llama Next() para generar dos números enteros, uno por 32 izquierda-desplaza los bits y OR ellos juntos. Esta técnica tiene dos limitaciones:

  1. Dado que el bit 31 es el bit de signo, el valor de bit 31 del entero largo resultante siempre es 0. Esto puede solucionarse generando un aleatorio 0 o 1, desplazamiento hacia la izquierda, 31 bits y OR de índices con el original entero largo aleatorio.

  2. Más en serio, ya que la probabilidad de que el valor devuelto por Next() será 0, habrá pocos si los números aleatorios en el intervalo 0 x 0 0x00000000FFFFFFFF.

Las sobrecargas de la Next método le permiten especificar el intervalo de números aleatorios, pero la NextBytes método no lo hace. En el ejemplo siguiente se implementa un NextBytes método que le permite especificar el intervalo de bytes devueltos. Define un Random2 clase que deriva de Random y overloads su NextBytes método.

using System;

public class Example
{
   public static void Main()
   {
       Random2 rnd = new Random2();
       Byte[] bytes = new Byte[10000];
       int[] total = new int[101];
       rnd.NextBytes(bytes, 0, 101);

       // Calculate how many of each value we have.
       foreach (var value in bytes)
          total[value]++;

       // Display the results.
       for (int ctr = 0; ctr < total.Length; ctr++) {
           Console.Write("{0,3}: {1,-3}   ", ctr, total[ctr]);
           if ((ctr + 1) % 5 == 0) Console.WriteLine();
       }   
   }
}

public class Random2 : Random
{
   public Random2() : base()
   {}

   public Random2(int seed) : base(seed)
   {}

   public void NextBytes(byte[] bytes, byte minValue, byte maxValue)
   {
      for (int ctr = bytes.GetLowerBound(0); ctr <= bytes.GetUpperBound(0); ctr++)
         bytes[ctr] = (byte) Next(minValue, maxValue);
   }
}
// The example displays output like the following:
//         0: 115     1: 119     2: 92      3: 98      4: 92
//         5: 102     6: 103     7: 84      8: 93      9: 116
//        10: 91     11: 98     12: 106    13: 91     14: 92
//        15: 101    16: 100    17: 96     18: 97     19: 100
//        20: 101    21: 106    22: 112    23: 82     24: 85
//        25: 102    26: 107    27: 98     28: 106    29: 102
//        30: 109    31: 108    32: 94     33: 101    34: 107
//        35: 101    36: 86     37: 100    38: 101    39: 102
//        40: 113    41: 95     42: 96     43: 89     44: 99
//        45: 81     46: 89     47: 105    48: 100    49: 85
//        50: 103    51: 103    52: 93     53: 89     54: 91
//        55: 97     56: 105    57: 97     58: 110    59: 86
//        60: 116    61: 94     62: 117    63: 98     64: 110
//        65: 93     66: 102    67: 100    68: 105    69: 83
//        70: 81     71: 97     72: 85     73: 70     74: 98
//        75: 100    76: 110    77: 114    78: 83     79: 90
//        80: 96     81: 112    82: 102    83: 102    84: 99
//        85: 81     86: 100    87: 93     88: 99     89: 118
//        90: 95     91: 124    92: 108    93: 96     94: 104
//        95: 106    96: 99     97: 99     98: 92     99: 99
//       100: 108

El NextBytes(Byte[], Byte, Byte) método ajusta una llamada a la Next(Int32, Int32) (método) y especifica el valor mínimo y uno mayor que el valor máximo (en este caso, 0 y 101) que deseamos devueltos en la matriz de bytes. Dado que estamos seguros de que los valores enteros devuelven por la Next método están dentro del intervalo de la Byte el tipo de datos, podemos segura convertirlos (en C#) o convertirlos (en Visual Basic) de enteros y bytes.

Números aleatorios sirven a menudo como índices para recuperar valores de las matrices o colecciones. Para recuperar un valor de índice aleatorio, puede llamar a la Next(Int32, Int32) método y use el límite inferior de la matriz como valor de su minValue argumento y una unidad mayor que el límite superior de la matriz como el valor de su maxValue argumento. Para una matriz de base cero, esto es equivalente a su Length propiedad o una unidad mayor que el valor devuelto por la Array.GetUpperBound (método). En el ejemplo siguiente se recupera de forma aleatoria el nombre de una ciudad en Estados Unidos desde una matriz de ciudades.

using System;

public class Example
{
   public static void Main()
   {
      String[] cities = { "Atlanta", "Boston", "Chicago", "Detroit", 
                          "Fort Wayne", "Greensboro", "Honolulu", "Indianapolis", 
                          "Jersey City", "Kansas City", "Los Angeles", 
                          "Milwaukee", "New York", "Omaha", "Philadelphia", 
                          "Raleigh", "San Francisco", "Tulsa", "Washington" };
      Random rnd = new Random();
      int index = rnd.Next(0, cities.Length);
      Console.WriteLine("Today's city of the day: {0}",
                        cities[index]);                           
   }
}
// The example displays output like the following:
//   Today's city of the day: Honolulu

Un generador de números aleatorios siempre puede devolver valores duplicados. Como el intervalo de números se vuelve más pequeño o el número de valores generados aumenta de tamaño, aumenta la probabilidad de duplicados. Si valores aleatorios deben ser únicos, más números se generan para compensar los duplicados, lo que resulta en un rendimiento más bajo.

Existen varias técnicas para controlar este escenario. Una solución habitual es crear una matriz o colección que contiene los valores que se van a recuperar y una matriz paralela que contiene los números de punto flotante aleatorios. La segunda matriz se rellena con números aleatorios en el momento en que se crea la primera matriz, y la Array.Sort(Array, Array) método se utiliza para ordenar la primera matriz con los valores de la matriz en paralelo.

Por ejemplo, si está desarrollando un juego Solitario, desea asegurarse de que se utiliza sólo una vez cada tarjeta. En lugar de generar números aleatorios para recuperar una tarjeta y el seguimiento de si ya ha se ha trabajado esa tarjeta, puede crear una matriz paralela de números aleatorios que se pueden utilizar para ordenar la cubierta. Una vez que se ordena la cubierta, la aplicación puede mantener un puntero para indicar el índice de la tarjeta siguiente en la cubierta.

En el ejemplo siguiente se muestra este enfoque. Define un Card clase que representa una carta de una baraja y un Dealer (clase) que se encarga de una baraja de cartas orden aleatorios. El Dealer constructor de clase rellena dos matrices: una deck matriz que tiene ámbito de clase y que representa todas las cartas de la baraja; y una variable local order matriz que tiene el mismo número de elementos como el deck de matriz y se rellena con generada al azar Double valores. El Array.Sort(Array, Array) a continuación, se llama el método para ordenar el deck matriz basándose en los valores en el order matriz.

using System;

// A class that represents an individual card in a playing deck.
public class Card
{
   public Suit Suit; 
   public FaceValue FaceValue;

   public override String ToString() 
   {
      return String.Format("{0:F} of {1:F}", this.FaceValue, this.Suit);
   }
}

public enum Suit { Hearts, Diamonds, Spades, Clubs };

public enum FaceValue  { Ace = 1, Two, Three, Four, Five, Six,
                         Seven, Eight, Nine, Ten, Jack, Queen,
                         King };

public class Dealer
{
   Random rnd;
   // A deck of cards, without Jokers.
   Card[] deck = new Card[52];
   // Parallel array for sorting cards.
   Double[] order = new Double[52];
   // A pointer to the next card to deal.
   int ptr = 0;
   // A flag to indicate the deck is used.
   bool mustReshuffle = false;

   public Dealer()
   {
      rnd = new Random();
      // Initialize the deck.
      int deckCtr = 0;
      foreach (var suit in Enum.GetValues(typeof(Suit))) {
         foreach (var faceValue in Enum.GetValues(typeof(FaceValue))) { 
            Card card = new Card();
            card.Suit = (Suit) suit;
            card.FaceValue = (FaceValue) faceValue;
            deck[deckCtr] = card;  
            deckCtr++;
         }
      }

      for (int ctr = 0; ctr < order.Length; ctr++)
         order[ctr] = rnd.NextDouble();   

      Array.Sort(order, deck);
   }

   public Card[] Deal(int numberToDeal)
   {
      if (mustReshuffle) {
         Console.WriteLine("There are no cards left in the deck");
         return null;
      }

      Card[] cardsDealt = new Card[numberToDeal];
      for (int ctr = 0; ctr < numberToDeal; ctr++) {
         cardsDealt[ctr] = deck[ptr];
         ptr++;
         if (ptr == deck.Length) 
            mustReshuffle = true;

         if (mustReshuffle & ctr < numberToDeal - 1) {
            Console.WriteLine("Can only deal the {0} cards remaining on the deck.", 
                              ctr + 1);
            return cardsDealt;
         }
      }
      return cardsDealt;
   }
}


public class Example
{
   public static void Main()
   {
      Dealer dealer = new Dealer();
      ShowCards(dealer.Deal(20));
   }

   private static void ShowCards(Card[] cards)
   {
      foreach (var card in cards)
         if (card != null)
            Console.WriteLine("{0} of {1}", card.FaceValue, card.Suit);
   }
}
// The example displays output like the following:
//       Six of Diamonds
//       King of Clubs
//       Eight of Clubs
//       Seven of Clubs
//       Queen of Clubs
//       King of Hearts
//       Three of Spades
//       Ace of Clubs
//       Four of Hearts
//       Three of Diamonds
//       Nine of Diamonds
//       Two of Hearts
//       Ace of Hearts
//       Three of Hearts
//       Four of Spades
//       Eight of Hearts
//       Queen of Diamonds
//       Two of Clubs
//       Four of Diamonds
//       Jack of Hearts

Notas para llamadores:

La implementación del generador de números aleatorios en la Random clase no está garantizada que siguen siendo los mismos en las versiones principales de .NET Framework. Como resultado, no debe asumir que dará como resultado el mismo valor de inicialización en la misma secuencia pseudoaleatoria en diferentes versiones de .NET Framework.

Notas para desarrolladores de herederos:

En .NET Framework 1.0 y 1.1, una implementación mínima de una clase derivada de Random necesario reemplazar el Sample método para definir un algoritmo nuevo o modificado para generar números aleatorios. La clase derivada podría dependen de la implementación de la clase base de la Random.Next(), Random.Next(Int32), Random.Next(Int32, Int32), NextBytes, y NextDouble métodos para llamar a la implementación de la clase derivada de la Sample (método).

En .NET Framework 2.0 y versiones posterior, el comportamiento de la Random.Next(), Random.Next(Int32, Int32), y NextBytes han cambiado los métodos para que estos métodos no llaman necesariamente a la implementación de la clase derivada de la Sample (método). Como resultado, las clases derivadas de Random que como destino .NET Framework 2.0 y posterior también deben invalidar estos tres métodos.

En el ejemplo siguiente se crea un generador de números aleatorios único y llama su NextBytes, Next, y NextDouble métodos para generar secuencias de números aleatorios en intervalos diferentes.

using System;

public class Class1
{
   public static void Main()
   {
      // 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);
   }
}
// The example displays output like the following:
//    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

En el ejemplo siguiente se genera un número entero que usa como índice para recuperar un valor de cadena de una matriz.

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

Plataforma universal de Windows
Disponible desde 8
.NET Framework
Disponible desde 1.1
Biblioteca de clases portable
Se admite en: plataformas portátiles de .NET
Silverlight
Disponible desde 2.0
Windows Phone Silverlight
Disponible desde 7.0
Windows Phone
Disponible desde 8.1

Cualquier miembro ( Compartido en Visual Basic) estático público de este tipo es seguro para subprocesos. No se garantiza que los miembros de instancia sean seguros para subprocesos.

Volver al principio
Mostrar: