Random Random Random Random Class

Определение

Представляет генератор псевдослучайных чисел, то есть устройство, которое выдает последовательность чисел, отвечающую определенным статистическим критериям случайности.Represents a pseudo-random number generator, which is a device that produces a sequence of numbers that meet certain statistical requirements for randomness.

public ref class Random
[System.Runtime.InteropServices.ComVisible(true)]
[System.Serializable]
public class Random
type Random = class
Public Class Random
Наследование
RandomRandomRandomRandom
Атрибуты

Примеры

В следующем примере создается один генератор случайных чисел и вызывается его NextBytesметоды Next, и NextDouble для создания последовательностей случайных чисел в разных диапазонах.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.

using namespace System;

void main()
{
   // Instantiate random number generator using system-supplied value as seed.
   Random^ rand = gcnew Random();
   // Generate and display 5 random byte (integer) values.
   array<Byte>^ bytes = gcnew array<Byte>(4);
   rand->NextBytes(bytes);
   Console::WriteLine("Five random byte values:");
   for each (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
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[5];
      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
Module Example
   Public Sub Main()
      ' Instantiate random number generator using system-supplied value as seed.
      Dim rand As New Random()
      ' Generate and display 5 random byte (integer) values.
      Dim bytes(4) As Byte
      rand.NextBytes(bytes)
      Console.WriteLine("Five random byte values:")
      For Each byteValue As Byte In bytes
         Console.Write("{0, 5}", byteValue)
      Next
      Console.WriteLine()   
      ' Generate and display 5 random integers.
      Console.WriteLine("Five random integer values:")
      For ctr As Integer = 0 To 4
         Console.Write("{0,15:N0}", rand.Next)
      Next                     
      Console.WriteLine()
      ' Generate and display 5 random integers between 0 and 100.'
      Console.WriteLine("Five random integers between 0 and 100:")
      For ctr As Integer = 0 To 4
         Console.Write("{0,8:N0}", rand.Next(101))
      Next                     
      Console.WriteLine()
      ' Generate and display 5 random integers from 50 to 100.
      Console.WriteLine("Five random integers between 50 and 100:")
      For ctr As Integer = 0 To 4
         Console.Write("{0,8:N0}", rand.Next(50, 101))
      Next                     
      Console.WriteLine()
      ' Generate and display 5 random floating point values from 0 to 1.
      Console.WriteLine("Five Doubles.")
      For ctr As Integer = 0 To 4
         Console.Write("{0,8:N3}", rand.NextDouble())
      Next                     
      Console.WriteLine()
      ' Generate and display 5 random floating point values from 0 to 5.
      Console.WriteLine("Five Doubles between 0 and 5.")
      For ctr As Integer = 0 To 4
         Console.Write("{0,8:N3}", rand.NextDouble() * 5)
      Next                     
   End Sub
End Module
' 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

В следующем примере создается случайное целое число, которое используется в качестве индекса для получения строкового значения из массива.The following example generates a random integer that it uses as an index to retrieve a string value from an array.

using namespace System;

void main()
{
   Random^ rnd = gcnew Random();
   array<String^>^ malePetNames = { "Rufus", "Bear", "Dakota", "Fido",
                                    "Vanya", "Samuel", "Koani", "Volodya",
                                    "Prince", "Yiska" };
   array<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
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
Module Example
   Public Sub Main()
      Dim rnd As New Random()
      Dim malePetNames() As String = { "Rufus", "Bear", "Dakota", "Fido", 
                                    "Vanya", "Samuel", "Koani", "Volodya", 
                                    "Prince", "Yiska" }
      Dim femalePetNames() As String = { "Maggie", "Penny", "Saya", "Princess", 
                                         "Abby", "Laila", "Sadie", "Olivia", 
                                         "Starlight", "Talla" }                                      
      
      ' Generate random indexes for pet names.
      Dim mIndex As Integer = rnd.Next(malePetNames.Length)
      Dim fIndex As Integer = 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))
   End Sub
End Module
' The example displays output like the following:
'       Suggested pet name of the day:
'          For a male:     Koani
'          For a female:   Maggie

Комментарии

Псевдо-случайные числа выбираются с равной вероятностью из конечного набора чисел.Pseudo-random numbers are chosen with equal probability from a finite set of numbers. Выбранные числа не являются полностью случайными, поскольку для их выбора используется математический алгоритм, но они достаточно случайные для практических целей.The chosen numbers are not completely random because a mathematical algorithm is used to select them, but they are sufficiently random for practical purposes. Текущая реализация Random класса основана на измененной версии алгоритма генератора случайных чисел Дональд E. кнута с вычитанием.The current implementation of the Random class is based on a modified version of Donald E. Knuth's subtractive random number generator algorithm. Дополнительные сведения см. в разделе D. E.For more information, see D. E. Кнута.Knuth. Искусство компьютерной программирования, том 2: Алгоритмысеминумерикал.The Art of Computer Programming, Volume 2: Seminumerical Algorithms. Addison-Wesley, чтение, MA, третий выпуск, 1997.Addison-Wesley, Reading, MA, third edition, 1997.

Чтобы создать криптографически защищенное случайное число, например подходящее для создания случайного пароля, используйте RNGCryptoServiceProvider класс или наследует класс от. System.Security.Cryptography.RandomNumberGeneratorTo generate a cryptographically secure random number, such as one that's suitable for creating a random password, use the RNGCryptoServiceProvider class or derive a class from System.Security.Cryptography.RandomNumberGenerator.

В этом разделе.In this topic:

Создание экземпляра генератора случайных чисел Instantiating the random number generator
Предотвращение нескольких экземпляров Avoiding multiple instantiations
Класс System. Random и безопасность потоков The System.Random class and thread safety
Создание различных типов случайных чисел Generating different types of random numbers
Замена собственного алгоритма Substituting your own algorithm
Как использовать System. Random to... How do you use System.Random to…
Получение той же последовательности случайных значенийRetrieve the same sequence of random values
Получение уникальных последовательностей случайных значенийRetrieve unique sequences of random values
Получение целых чисел в указанном диапазонеRetrieve integers in a specified range
Получение целых чисел с указанным числом цифрRetrieve integers with a specified number of digits
Получение значений с плавающей запятой в указанном диапазонеRetrieve floating-point values in a specified range
Создание случайных логических значенийGenerate random Boolean values
Создавать случайные 64-разрядные целые числаGenerate random 64-bit integers
Извлечение байтов в указанном диапазонеRetrieve bytes in a specified range
Извлечение элемента из массива или коллекции в случайном порядкеRetrieve an element from an array or collection at random
Извлечение уникального элемента из массива или коллекцииRetrieve a unique element from an array or collection

Создание экземпляра генератора случайных чиселInstantiating the random number generator

Чтобы создать экземпляр генератора случайных чисел, укажите начальное значение (начальное значение для алгоритма формирования псевдо-случайных чисел) конструктору Random класса.You instantiate the random number generator by providing a seed value (a starting value for the pseudo-random number generation algorithm) to a Random class constructor. Начальное значение можно указать явно или неявно:You can supply the seed value either explicitly or implicitly:

  • Random(Int32) Конструктор использует явно указываемое начальное значение.The Random(Int32) constructor uses an explicit seed value that you supply.

  • Для предоставления начального значения конструкториспользуетсистемныечасы.Random()The Random() constructor uses the system clock to provide a seed value. Это наиболее распространенный способ создания экземпляра генератора случайных чисел.This is the most common way of instantiating the random number generator.

Если для отдельных Random объектов используется одно и то же начальное значение, они будут создавать одинаковые ряды случайных чисел.If the same seed is used for separate Random objects, they will generate the same series of random numbers. Это может быть полезно для создания набора тестов, который обрабатывает случайные значения или для воспроизведения игр, которые наследуют данные от случайных чисел.This can be useful for creating a test suite that processes random values, or for replaying games that derive their data from random numbers. Однако обратите внимание Random , что объекты в процессах, выполняющихся в разных версиях .NET Framework, могут возвращать разные серии случайных чисел, даже если они создаются с одинаковыми начальными значениями.However, note that Random objects in processes running under different versions of the .NET Framework may return different series of random numbers even if they're instantiated with identical seed values.

Для создания различных последовательностей случайных чисел можно сделать начальное значение зависимым от времени, тем самым создавая другой ряд с каждым новым экземпляром Random.To produce different sequences of random numbers, you can make the seed value time-dependent, thereby producing a different series with each new instance of Random. Параметризованный Random(Int32) конструктор может Int32 принимать значение на основе числа тактов в текущем времени, Random() тогда как конструктор без параметров использует системные часы для создания начального значения.The parameterized Random(Int32) constructor can take an Int32 value based on the number of ticks in the current time, whereas the parameterless Random() constructor uses the system clock to generate its seed value. Однако, поскольку часы имеют конечное разрешение, использование конструктора без параметров для создания различных Random объектов в случае закрытия завершает создание генераторов случайных чисел, создающих идентичные последовательности случайных чисел.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. В следующем примере показано, как Random два объекта, создаваемые при закрытии, формируют идентичные последовательности случайных чисел.The following example illustrates how two Random objects that are instantiated in close succession generate an identical series of random numbers. В большинстве систем Windows объекты Random , созданные в течение 15 миллисекунд, могут иметь одинаковые начальные значения.On most Windows systems, Random objects created within 15 milliseconds of one another are likely to have identical seed values.

using namespace System;

void main()
{
   array<Byte>^ bytes1 = gcnew array<Byte>(100);
   array<Byte>^ bytes2 = gcnew array<Byte>(100);
   Random^ rnd1 = gcnew Random();
   Random^ rnd2 = gcnew 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        
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        
Module modMain

   Public Sub Main()
      Dim bytes1(99), bytes2(99) As Byte
      Dim rnd1 As New Random()
      Dim rnd2 As New Random()
      
      rnd1.NextBytes(bytes1)
      rnd2.NextBytes(bytes2)
      
      Console.WriteLine("First Series:")
      For ctr As Integer = bytes1.GetLowerBound(0) to bytes1.GetUpperBound(0)
         Console.Write("{0, 5}", bytes1(ctr))
         If (ctr + 1) Mod 10 = 0 Then Console.WriteLine()
      Next 
      Console.WriteLine()
      Console.WriteLine("Second Series:")        
      For ctr As Integer = bytes2.GetLowerBound(0) to bytes2.GetUpperBound(0)
         Console.Write("{0, 5}", bytes2(ctr))
         If (ctr + 1) Mod 10 = 0 Then Console.WriteLine()
      Next   
   End Sub
End Module
' 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      

Чтобы избежать этой проблемы, создайте один Random объект, а не несколько объектов.To avoid this problem, create a single Random object instead of multiple objects.

Предотвращение нескольких экземпляровAvoiding multiple instantiations

Инициализация двух генераторов случайных чисел в тесном цикле или при быстром выполнении создает два генератора случайных чисел, которые могут формировать идентичные последовательности случайных чисел.Initializing two random number generators in a tight loop or in rapid succession creates two random number generators that can produce identical sequences of random numbers. В большинстве случаев это не является намерением разработчика и может привести к проблемам с производительностью, поскольку создание и инициализация генератора случайных чисел является сравнительно дорогостоящим процессом.In most cases, this is not the developer's intent and can lead to performance issues, because instantiating and initializing a random number generator is a relatively expensive process.

Чтобы повысить производительность и избежать случайного создания отдельных генераторов случайных чисел, создающих идентичные числовые последовательности, рекомендуется создать один Random объект для создания множества случайных чисел с течением времени, а не создавать новые Random объекты для создания одного случайного числа.Both to improve performance and to avoid inadvertently creating separate random number generators that generate identical numeric sequences, we recommend that you create one Random object to generate many random numbers over time, instead of creating new Random objects to generate one random number.

Random Однако класс не является потокобезопасным.However, the Random class isn't thread safe. При вызове Random методов из нескольких потоков следуйте рекомендациям, изложенным в следующем разделе.If you call Random methods from multiple threads, follow the guidelines discussed in the next section.

Класс System. Random и безопасность потоковThe System.Random class and thread safety

Вместо создания экземпляров отдельных Random объектов рекомендуется создать один Random экземпляр для создания всех случайных чисел, необходимых для приложения.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. Random Однако объекты не являются потокобезопасными.However, Random objects are not thread safe. Если приложение вызывает Random методы из нескольких потоков, необходимо использовать объект синхронизации, чтобы убедиться, что только один поток может одновременно получить доступ к генератору случайных чисел.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. Если не гарантировать, что Random доступ к объекту осуществляется потокобезопасным способом, вызовы методов, возвращающих случайные числа, возвращают 0.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.

В следующем примере используется C# оператор lock и оператор Visual Basic SyncLock , чтобы гарантировать, что один генератор случайных чисел обращается к 11 потокам потокобезопасным образом.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. Каждый поток создает 2 000 000 случайных чисел, подсчитывает количество создаваемых случайных чисел и вычисляет их сумму, а затем обновляет итоги для всех потоков после завершения выполнения.Each thread generates 2 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 namespace System;
using namespace System::Threading;

ref class Example
{
private:
   [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;
   static Object^ numericLock;
   static Random^ rand;
   double totalValue = 0.0;
   int totalCount = 0;
   
public:
   Example()
   { 
      rand = gcnew Random();
      randLock = gcnew Object();
      numericLock = gcnew Object();
      countdown = gcnew CountdownEvent(1);
      source = gcnew CancellationTokenSource();
   } 

   void Execute()
   {   
      CancellationToken^ token = source->Token;

      for (int threads = 1; threads <= 10; threads++)
      {
         Thread^ newThread = gcnew Thread(gcnew ParameterizedThreadStart(this, &Example::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();

            Monitor::Enter(randLock);
            result = rand->NextDouble();
            Monitor::Exit(randLock);
            // 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.
         Monitor::Enter(numericLock);
         totalCount += perThreadCtr;
         totalValue += perThreadTotal;  
         Monitor::Exit(numericLock);
      }
      catch (OperationCanceledException^ e) {
         Console::WriteLine("Corruption in Thread {1}", e->GetType()->Name,
                            Thread::CurrentThread->Name);
      }
      finally {
         countdown->Signal();
      }
   }
};

void main()
{
   Example^ ex = gcnew Example();
   Thread::CurrentThread->Name = "Main";
   ex->Execute();
}
// 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
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
Imports System.Threading

Module Example
   <ThreadStatic> Dim previous As Double = 0.0
   <ThreadStatic> Dim perThreadCtr As Integer = 0
   <ThreadStatic> Dim perThreadTotal As Double = 0.0  
   Dim source As New CancellationTokenSource()
   Dim countdown As New CountdownEvent(1) 
   Dim randLock As New Object()
   Dim numericLock As New Object()
   Dim rand As New Random()
   Dim totalValue As Double = 0.0
   Dim totalCount As Integer = 0
   
   Public Sub Main()
      Thread.CurrentThread.Name = "Main"

      Dim token As CancellationToken = source.Token 
      For threads As Integer = 1 To 10
         Dim newThread As New Thread(AddressOf GetRandomNumbers)
         newThread.Name = threads.ToString()
         newThread.Start(token)
      Next
      GetRandomNumbers(token)
      
      countdown.Signal()
      ' Make sure all threads have finished.
      countdown.Wait()

      Console.WriteLine()
      Console.WriteLine("Total 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)
   End Sub

   Private Sub GetRandomNumbers(o As Object)
      Dim token As CancellationToken = CType(o, CancellationToken)
      Dim result As Double = 0.0
      countdown.AddCount(1)
         
      Try  
         For ctr As Integer = 1 To 2000000
            ' Make sure there's no corruption of Random.
            token.ThrowIfCancellationRequested()

            SyncLock randLock
               result = rand.NextDouble()
            End SyncLock
            ' Check for corruption of Random instance.
            If result = previous AndAlso result = 0 Then 
               source.Cancel()
            Else 
               previous = result
            End If
            perThreadCtr += 1
            perThreadTotal += result
         Next      
       
         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}", perThreadTotal/perThreadCtr)
         Console.WriteLine()
         
         ' Update overall totals.
         SyncLock numericLock
            totalCount += perThreadCtr
            totalValue += perThreadTotal  
         End SyncLock
      Catch e As OperationCanceledException
         Console.WriteLine("Corruption in Thread {1}", e.GetType().Name, Thread.CurrentThread.Name)
      Finally 
         countdown.Signal()
         source.Dispose()
      End Try
   End Sub
End Module
' 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:

  • ThreadStaticAttribute Атрибут используется для определения локальных переменных потока, которые отправляют общее число формируемых случайных чисел и их сумму для каждого потока.The ThreadStaticAttribute attribute is used to define thread-local variables that track the total number of random numbers generated and their sum for each thread.

  • Блокировка ( lock оператор в C# и SyncLock оператор в Visual Basic) обеспечивает защиту доступа к переменным для общего количества и суммирования всех случайных чисел, созданных во всех потоках.A lock (the lock statement in C# and the SyncLock statement in Visual Basic) protects access to the variables for the total count and sum of all random numbers generated on all threads.

  • Семафор ( CountdownEvent объект) используется, чтобы обеспечить блокировку основного потока до завершения выполнения всех остальных потоков.A semaphore (the CountdownEvent object) is used to ensure that the main thread blocks until all other threads complete execution.

  • В примере проверяется, поврежден ли генератор случайных чисел, путем определения, будут ли два последовательных вызова методов генерации случайных чисел возвращать 0.The example checks whether the random number generator has become corrupted by determining whether two consecutive calls to random number generation methods return 0. Если обнаружено повреждение, в примере используется CancellationTokenSource объект для сигнализации о том, что все потоки должны быть отменены.If corruption is detected, the example uses the CancellationTokenSource object to signal that all threads should be canceled.

  • Перед созданием каждого случайного числа каждый поток проверяет состояние CancellationToken объекта.Before generating each random number, each thread checks the state of the CancellationToken object. При запросе отмены в примере вызывается CancellationToken.ThrowIfCancellationRequested метод для отмены потока.If cancellation is requested, the example calls the CancellationToken.ThrowIfCancellationRequested method to cancel the thread.

Следующий пример идентичен первому, за исключением того, что он использует Task объект и лямбда-выражение 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 async Task Main()
   {
      Example ex = new Example();
      Thread.CurrentThread.Name = "Main";
      await ex.Execute();
   }

   private Task 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 {
         await Task.WhenAll(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
Imports System.Collections.Generic
Imports System.Threading
Imports System.Threading.Tasks

Module Example
   Dim source As New CancellationTokenSource()
   Dim randLock As New Object()
   Dim numericLock As New Object()
   Dim rand As New Random()
   Dim totalValue As Double = 0.0
   Dim totalCount As Integer = 0
   
   Public Sub Main()
      Dim tasks As New List(Of Task)()
      
      For ctr As Integer = 1 To 10
         Dim token As CancellationToken = source.Token 
         Dim taskNo As Integer = ctr
         tasks.Add(Task.Run( 
                   Sub()
                      Dim previous As Double = 0.0
                      Dim taskCtr As Integer = 0
                      Dim taskTotal As Double = 0.0
                      Dim result As Double = 0.0

                      For n As Integer = 1 To 2000000
                         ' Make sure there's no corruption of Random.
                         token.ThrowIfCancellationRequested()
      
                         SyncLock randLock
                           result = rand.NextDouble()
                         End SyncLock
                         ' Check for corruption of Random instance.
                         If result = previous AndAlso result = 0 Then
                           source.Cancel()
                         Else 
                           previous = result
                         End If
                        taskCtr += 1
                        taskTotal += result
                      Next   

                      ' 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}", taskTotal/taskCtr)
                     Console.WriteLine()
                     
                     ' Update overall totals.
                     SyncLock numericLock
                        totalCount += taskCtr
                        totalValue += taskTotal  
                     End SyncLock
                   End Sub, token))
      Next

      Try
         Task.WaitAll(tasks.ToArray())
         Console.WriteLine()
         Console.WriteLine("Total 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 e As AggregateException
         For Each inner As Exception In e.InnerExceptions
            Dim canc As TaskCanceledException = TryCast(inner, TaskCanceledException)
            If canc IsNot Nothing Then
               Console.WriteLine("Task #{0} cancelled.", canc.Task.Id)
            Else
               Console.WriteLine("Exception: {0}", inner.GetType().Name)
            End If   
         Next         
      Finally
         source.Dispose()
      End Try
   End Sub
End Module
' 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:

  • Переменные, которые следует отследить от количества формируемых случайных чисел и их сумму в каждой задаче, являются локальными для задачи, поэтому нет необходимости использовать ThreadStaticAttribute атрибут.The variables to keep track of the number of random numbers generated and their sum in each task are local to the task, so there is no need to use the ThreadStaticAttribute attribute.

  • Статический Task.WaitAll метод используется, чтобы гарантировать, что главный поток не завершится до завершения всех задач.The static Task.WaitAll method is used to ensure that the main thread doesn't complete before all tasks have finished. CountdownEvent Объект не требуется.There is no need for the CountdownEvent object.

  • Исключение, полученное в результате отмены задачи, отображается в Task.WaitAll методе.The exception that results from task cancellation is surfaced in the Task.WaitAll method. В предыдущем примере он обрабатывается каждым потоком.In the previous example, it is handled by each thread.

Создание различных типов случайных чиселGenerating different types of random numbers

Генератор случайных чисел предоставляет методы, позволяющие создавать следующие виды случайных чисел:The random number generator provides methods that let you generate the following kinds of random numbers:

  • Ряд Byte значений.A series of Byte values. Вы определяете количество байтовых значений, передавая массив, инициализируемый в число элементов, которые метод должен вернуть NextBytes в метод.You determine the number of byte values by passing an array initialized to the number of elements you want the method to return to the NextBytes method. Следующий пример приводит к возникновению 20 байтов.The following example generates 20 bytes.

    using namespace System;
    
    void main()
    {
       Random^ rnd = gcnew Random();
       array<Byte>^ bytes = gcnew array<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
    
    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
    
    Module Example
       Public Sub Main()
          Dim rnd As New Random()
          Dim bytes(19) As Byte
          rnd.NextBytes(bytes)  
          For ctr As Integer = 1 To bytes.Length
             Console.Write("{0,3}   ", bytes(ctr - 1))
             If ctr Mod 10 = 0 Then Console.WriteLine()
          Next 
       End Sub
    End Module
    ' 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
    
  • Одно целое число.A single integer. Можно выбрать, требуется ли целое число от 0 до максимального значения (Int32.MaxValue -1), Next() вызвав метод, целое число от 0 до Next(Int32) определенного значения путем вызова метода или целого числа в диапазоне значений, вызвав метод Next(Int32, Int32)метод.You can choose whether you want an integer from 0 to a maximum value (Int32.MaxValue - 1) by calling the Next() method, an integer between 0 and a specific value by calling the Next(Int32) method, or an integer within a range of values by calling the Next(Int32, Int32) method. В параметризованных перегрузках указанное максимальное значение является эксклюзивным; то есть фактическое максимальное число, созданное на единицу, меньше указанного значения.In the parameterized overloads, the specified maximum value is exclusive; that is, the actual maximum number generated is one less than the specified value.

    В следующем примере вызывается Next(Int32, Int32) метод для создания 10 случайных чисел в диапазоне от-10 до 10.The following example calls the Next(Int32, Int32) method to generate 10 random numbers between -10 and 10. Обратите внимание, что второй аргумент метода указывает эксклюзивную верхнюю границу диапазона случайных значений, возвращаемых методом.Note that the second argument to the method specifies the exclusive upper bound of the range of random values returned by the method. Иными словами, самое большое целое число, которое метод может вернуть, меньше этого значения.In other words, the largest integer that the method can return is one less than this value.

    using namespace System;
    
    void main()
    {
       Random^ rnd = gcnew 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
    
    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
    
    Module Example
       Public Sub Main()
          Dim rnd As New Random()
          For ctr As Integer = 0 To 9
             Console.Write("{0,3}   ", rnd.Next(-10, 11))
          Next
       End Sub
    End Module
    ' The example displays output like the following:
    '    2     9    -3     2     4    -7    -3    -8    -8     5
    
  • Одиночное значение с плавающей запятой от 0,0 до меньше 1,0 путем вызова NextDouble метода.A single floating-point value from 0.0 to less than 1.0 by calling the NextDouble method. Эксклюзивная верхняя граница случайного числа, возвращаемого методом, — 1, поэтому фактическая верхняя граница — 0.99999999999999978.The exclusive upper bound of the random number returned by the method is 1, so its actual upper bound is 0.99999999999999978. В следующем примере создаются 10 случайных чисел с плавающей запятой.The following example generates 10 random floating-point numbers.

    using namespace System;
    
    void main()
    {
       Random^ rnd = gcnew 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
    
    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
    
    Module Example
       Public Sub Main()
          Dim rnd As New Random()
          For ctr As Integer = 0 To 9
             Console.Write("{0,-19:R}   ", rnd.NextDouble())
             If (ctr + 1) Mod 3 = 0 Then Console.WriteLine()
          Next
       End Sub
    End Module
    ' 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
    

Важно!

Next(Int32, Int32) Метод позволяет указать диапазон возвращаемого случайного числа.The Next(Int32, Int32) method allows you to specify the range of the returned random number. maxValue Однако параметр, который указывает верхний возвращенный диапазон, является эксклюзивным, а не инклюзивным значением.However, the maxValue parameter, which specifies the upper range returned number, is an exclusive, not an inclusive, value. Это означает, что вызов Next(0, 100) метода возвращает значение от 0 до 99, а не между 0 и 100.This means that the method call Next(0, 100) returns a value between 0 and 99, and not between 0 and 100.

Random Класс также можно использовать для таких задач, как создание случайных значений T:System.Boolean, создание случайных значений с плавающей запятой с диапазоном, отличным от 0 до 1, создание случайных 64-разрядных целых чисели случайное получение уникального элемента из массива или коллекции.You can also use the Random class for such tasks as generating random T:System.Boolean values, generating random floating point values with a range other than 0 to 1, generating random 64-bit integers, and randomly retrieving a unique element from an array or collection. Эти и другие распространенные задачи см. в разделе как использовать System. Random to...For these and other common tasks, see the How do you use System.Random to… раздела.section.

Замена собственного алгоритмаSubstituting your own algorithm

Вы можете реализовать собственный генератор случайных чисел, наследуя от Random класса и указав алгоритм создания случайных чисел.You can implement your own random number generator by inheriting from the Random class and supplying your random number generation algorithm. Чтобы указать собственный алгоритм, необходимо переопределить Sample метод, который реализует алгоритм создания случайных чисел.To supply your own algorithm, you must override the Sample method, which implements the random number generation algorithm. Также следует переопределить Next()методы, Next(Int32, Int32)и NextBytes , чтобы убедиться, что они вызывают переопределенный Sample метод.You should also override the Next(), Next(Int32, Int32), and NextBytes methods to ensure that they call your overridden Sample method. Вам не нужно переопределять Next(Int32) методы и. NextDoubleYou don't have to override the Next(Int32) and NextDouble methods.

Пример, который является производным от Random класса и изменяет генератор случайных чисел псевдослучайных значений по умолчанию, см. на Sample странице справки.For an example that derives from the Random class and modifies its default pseudo-random number generator, see the Sample reference page.

Как использовать System. Random to...How do you use System.Random to…

В следующих разделах приводятся примеры кода для некоторых способов использования случайных чисел в приложении.The following sections discuss and provide sample code for some of the ways you might want to use random numbers in your app.

Получение той же последовательности случайных значенийRetrieve the same sequence of random values

Иногда требуется создать одну и ту же последовательность случайных чисел в сценариях тестирования программного обеспечения и в игре.Sometimes you want to generate the same sequence of random numbers in software test scenarios and in game playing. Проверка с одинаковой последовательностью случайных чисел позволяет обнаруживать регрессию и подтверждать исправления ошибок.Testing with the same sequence of random numbers allows you to detect regressions and confirm bug fixes. Использование одинаковой последовательности случайных чисел в играх позволяет воспроизводить предыдущие игры.Using the same sequence of random number in games allows you to replay previous games.

Вы можете создать одну и ту же последовательность случайных чисел, предоставив Random(Int32) конструктору одно и то же начальное значение.You can generate the same sequence of random numbers by providing the same seed value to the Random(Int32) constructor. Начальное значение предоставляет начальное значение для алгоритма формирования псевдослучайных чисел.The seed value provides a starting value for the pseudo-random number generation algorithm. В следующем примере используется 100100 в качестве произвольного начального значения для создания экземпляра Random объекта, выводится 20 случайных значений с плавающей запятой и сохраняется начальное значение.The following example uses 100100 as an arbitrary seed value to instantiate the Random object, displays 20 random floating-point values, and persists the seed value. Затем оно восстанавливает начальное значение, создает новый генератор случайных чисел и отображает те же 20 случайных значений с плавающей точкой.It then restores the seed value, instantiates a new random number generator, and displays the same 20 random floating-point values. Обратите внимание, что в примере могут формироваться различные последовательности случайных чисел, если они работают в разных версиях .NET Framework.Note that the example may produce different sequences of random numbers if run on different versions of the .NET Framework.

using namespace System;
using namespace System::IO;

ref class RandomMethods
{
internal:
   static void ShowRandomNumbers(int seed)
   {
      Random^ rnd = gcnew Random(seed);
      for (int ctr = 0; ctr <= 20; ctr++)
         Console::WriteLine(rnd->NextDouble());
   }
   
   static void PersistSeed(int seed)
   {
      FileStream^ fs = gcnew FileStream(".\\seed.dat", FileMode::Create);
      BinaryWriter^ bin = gcnew BinaryWriter(fs);
      bin->Write(seed);
      bin->Close();
   }
   
   static void DisplayNewRandomNumbers()
   {
      FileStream^ fs = gcnew FileStream(".\\seed.dat", FileMode::Open);
      BinaryReader^ bin = gcnew BinaryReader(fs);
      int seed = bin->ReadInt32();
      bin->Close();
      
      Random^ rnd = gcnew Random(seed);
      for (int ctr = 0; ctr <= 20; ctr++)
         Console::WriteLine(rnd->NextDouble());
   }
};

void main()
{
   int seed = 100100;
   RandomMethods::ShowRandomNumbers(seed);
   Console::WriteLine();

   RandomMethods::PersistSeed(seed);

   RandomMethods::DisplayNewRandomNumbers();
}
// 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
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
Imports System.IO

Module Example
   Public Sub Main()
      Dim seed As Integer = 100100
      ShowRandomNumbers(seed)
      Console.WriteLine()
      
      PersistSeed(seed)
      
      DisplayNewRandomNumbers() 
   End Sub
   
   Private Sub ShowRandomNumbers(seed As Integer)
      Dim rnd As New Random(seed)
      For ctr As Integer = 0 To 20
         Console.WriteLine(rnd.NextDouble())
      Next
   End Sub
   
   Private Sub PersistSeed(seed As Integer)
      Dim fs As New FileStream(".\seed.dat", FileMode.Create)
      Dim bin As New BinaryWriter(fs)
      bin.Write(seed)
      bin.Close()
   End Sub
   
   Private Sub DisplayNewRandomNumbers()
      Dim fs As New FileStream(".\seed.dat", FileMode.Open)
      Dim bin As New BinaryReader(fs)
      Dim seed As Integer = bin.ReadInt32()
      bin.Close()
      
      Dim rnd As New Random(seed)
      For ctr As Integer = 0 To 20
         Console.WriteLine(rnd.NextDouble())
      Next
   End Sub
End Module
' 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

Получение уникальных последовательностей случайных чиселRetrieve unique sequences of random numbers

Предоставление различных начальных значений экземплярам Random класса приводит к тому, что каждый генератор случайных чисел создает другую последовательность значений.Providing different seed values to instances of the Random class causes each random number generator to produce a different sequence of values. Начальное значение можно указать явным образом путем вызова Random(Int32) конструктора или неявно путем Random() вызова конструктора.You can provide a seed value either explicitly by calling the Random(Int32) constructor, or implicitly by calling the Random() constructor. Большинство разработчиков вызывают конструктор без параметров, который использует системные часы.Most developers call the parameterless constructor, which uses the system clock. В следующем примере используется этот подход для создания экземпляров двух Random экземпляров.The following example uses this approach to instantiate two Random instances. Каждый экземпляр отображает последовательность из 10 случайных целых чисел.Each instance displays a series of 10 random integers.

using namespace System;
using namespace System::Threading;

void main()
{
   Console::WriteLine("Instantiating two random number generators...");
   Random^ rnd1 = gcnew Random();
   Thread::Sleep(2000);
   Random^ rnd2 = gcnew 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
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
Imports System.Threading

Module Example
   Public Sub Main()
      Console.WriteLine("Instantiating two random number generators...")
      Dim rnd1 As New Random()
      Thread.Sleep(2000)
      Dim rnd2 As New Random()
      Console.WriteLine()
      
      Console.WriteLine("The first random number generator:")
      For ctr As Integer = 1 To 10
         Console.WriteLine("   {0}", rnd1.Next())
      Next  
      Console.WriteLine()
       
      Console.WriteLine("The second random number generator:")
      For ctr As Integer = 1 To 10
         Console.WriteLine("   {0}", rnd2.Next())
      Next   
   End Sub
End Module
' 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

Однако из-за его конечного разрешения системные часы не обнаруживают разницы во времени, которые менее 15 миллисекунд.However, because of its finite resolution, the system clock doesn't detect time differences that are less than approximately 15 milliseconds. Таким образом, если код вызывает Random() перегрузку для создания экземпляров двух Random объектов, вы можете случайно предоставить объекты с одинаковыми начальными значениями.Therefore, if your code calls the Random() overload to instantiate two Random objects in succession, you might inadvertently be providing the objects with identical seed values. Чтобы увидеть это в предыдущем примере, закомментируйте Thread.Sleep вызов метода, а затем скомпилируйте и запустите пример еще раз.To see this in the previous example, comment out the Thread.Sleep method call, and compile and run the example again.

Чтобы предотвратить это, рекомендуется создать экземпляр одного Random объекта, а не несколько.To prevent this from happening, we recommend that you instantiate a single Random object rather than multiple ones. Однако, поскольку Random не является потокобезопасным, необходимо использовать некоторое устройство синхронизации при Random доступе к экземпляру из нескольких потоков. Дополнительные сведения см. в разделе случайный класс и безопасность потоков ранее в этой статье.However, since Random isn't thread safe, you must use some synchronization device if you access a Random instance from multiple threads; for more information, see The Random class and thread safety earlier in this topic. Кроме того, можно использовать механизм задержки, например Sleep метод, используемый в предыдущем примере, чтобы убедиться в том, что создание экземпляров происходит более чем на 15 миллисекунд.Alternately, you can use a delay mechanism, such as the Sleep method used in the previous example, to ensure that the instantiations occur more than 15 millisecond apart.

Получение целых чисел в указанном диапазонеRetrieve integers in a specified range

Вы можете получить целые числа в указанном диапазоне, вызвав Next(Int32, Int32) метод, который позволяет указать нижнюю и верхнюю границы чисел, которые нужно вернуть генератору случайных чисел.You can retrieve integers in a specified range by calling the Next(Int32, Int32) method, which lets you specify both the lower and the upper bound of the numbers you'd like the random number generator to return. Верхняя граница — это эксклюзивное, а не инклюзивное значение.The upper bound is an exclusive, not an inclusive, value. То есть он не включается в диапазон значений, возвращаемых методом.That is, it isn't included in the range of values returned by the method. В следующем примере этот метод используется для создания случайных целых чисел от-10 до 10.The following example uses this method to generate random integers between -10 and 10. Обратите внимание, что в нем указано значение 11, которое больше, чем требуемое значение, в maxValue качестве значения аргумента в вызове метода.Note that it specifies 11, which is one greater than the desired value, as the value of the maxValue argument in the method call.

using namespace System;

void main()
{
   Random^ rnd = gcnew 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
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
Module Example
   Public Sub Main()
      Dim rnd As New Random()
      For ctr As Integer = 1 To 15
         Console.Write("{0,3}    ", rnd.Next(-10, 11))
         If ctr Mod 5 = 0 Then Console.WriteLine()
      Next   
   End Sub
End Module
' The example displays output like the following:
'        -2     -5     -1     -2     10
'        -3      6     -4     -8      3
'        -7     10      5     -2      4

Получение целых чисел с указанным числом цифрRetrieve integers with a specified number of digits

Next(Int32, Int32) Метод можно вызвать для получения чисел с указанным числом цифр.You can call the Next(Int32, Int32) method to retrieve numbers with a specified number of digits. Например, чтобы получить числа с четырьмя цифрами (т. е. числа в диапазоне от 1000 до 9999), вызовите Next(Int32, Int32) метод minValue со maxValue значением 1000 и значением 10000, как показано в следующем примере.For example, to retrieve numbers with four digits (that is, numbers that range from 1000 to 9999), you call the Next(Int32, Int32) method with a minValue value of 1000 and a maxValue value of 10000, as the following example shows.

using namespace System;

void main()
{
   Random^ rnd = gcnew 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
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
Module Example
   Public Sub Main()
      Dim rnd As New Random()
      For ctr As Integer = 1 To 50
         Console.Write("{0,3}    ", rnd.Next(1000, 10000))
         If ctr Mod 10 = 0 Then Console.WriteLine()
      Next   
   End Sub
End Module
' 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

Получение значений с плавающей запятой в указанном диапазонеRetrieve floating-point values in a specified range

NextDouble Метод возвращает случайные значения с плавающей запятой в диапазоне от 0 до меньше 1.The NextDouble method returns random floating-point values that range from 0 to less than 1. Однако часто требуется создавать случайные значения в каком бы то ни было другом диапазоне.However, you'll often want to generate random values in some other range.

Если интервал между минимальным и максимальным требуемыми значениями равен 1, можно добавить разницу между требуемым начальным интервалом и значением 0 для числа, возвращаемого NextDouble методом.If the interval between the minimum and maximum desired values is 1, you can add the difference between the desired starting interval and 0 to the number returned by the NextDouble method. В следующем примере это делается для создания 10 случайных чисел в диапазоне от-1 до 0.The following example does this to generate 10 random numbers between -1 and 0.

using namespace System;

void main()
{
   Random^ rnd = gcnew 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
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
Module Example
   Public Sub Main()
      Dim rnd As New Random()
      For ctr As Integer = 1 To 10
         Console.WriteLine(rnd.NextDouble() - 1)
      Next
   End Sub
End Module
' 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

Для создания случайных чисел с плавающей запятой, Нижняя граница которых равна 0, но верхняя граница больше 1 (или, в случае отрицательных чисел, Нижняя граница которой меньше-1, а верхняя граница равна 0), умножьте случайное число на ненулевую границу.To generate random floating-point numbers whose lower bound is 0 but upper bound is greater than 1 (or, in the case of negative numbers, whose lower bound is less than -1 and upper bound is 0), multiply the random number by the non-zero bound. В следующем примере это делается для создания 20 000 000 случайных чисел с плавающей запятой в диапазоне от 0 Int64.MaxValueдо.The following example does this to generate 20 million random floating-point numbers that range from 0 to Int64.MaxValue. В также отображает распределение случайных значений, созданных методом.In also displays the distribution of the random values generated by the method.

using namespace System;

void main()
{
   const Int64 ONE_TENTH = 922337203685477581;
   Random^ rnd = gcnew Random();
   double number;
   array<int>^ count = gcnew array<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.
      int value = (int) (number / ONE_TENTH);
      count[value]++;
   }

   // 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 %
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 %
Module Example
   Public Sub Main()
      Const ONE_TENTH As Long = 922337203685477581

      Dim rnd As New Random()
      Dim number As Long
      Dim count(9) As Integer
      
      ' Generate 20 million integer values.
      For ctr As Integer = 1 To 20000000
         number = CLng(rnd.NextDouble() * Int64.MaxValue)
         ' Categorize random numbers.
         count(CInt(number \ ONE_TENTH)) += 1
      Next
      ' Display breakdown by range.
      Console.WriteLine("{0,28} {1,32}   {2,7}", "Range", "Count", "Pct.")
      Console.WriteLine()
      For ctr As Integer = 0 To 9
         Console.WriteLine("{0,25:N0}-{1,25:N0}  {2,8:N0}   {3,7:P2}", ctr * ONE_TENTH,
                            If(ctr < 9, ctr * ONE_TENTH + ONE_TENTH - 1, Int64.MaxValue), 
                            count(ctr), count(ctr)/20000000)
      Next
   End Sub
End Module
' 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 %

Чтобы создать случайные числа с плавающей запятой между двумя произвольными значениями, Next(Int32, Int32) например метод для целых чисел, используйте следующую формулу:To generate random floating-point numbers between two arbitrary values, like the Next(Int32, Int32) method does for integers, use the following formula:

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

Следующий пример приводит к возникновению ошибки 1 000 000 случайных чисел в диапазоне от 10,0 до 11,0 и отображении их распределения.The following example generates 1 million random numbers that range from 10.0 to 11.0, and displays their distribution.

using namespace System;

void main()
{
   Random^ rnd = gcnew Random();
   int lowerBound = 10;
   int upperBound = 11;
   array<int>^ range = gcnew array<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 %)
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 %)
Module Example
   Public Sub Main()
      Dim rnd As New Random()
      Dim lowerBound As Integer = 10
      Dim upperBound As Integer = 11
      Dim range(9) As Integer
      For ctr As Integer = 1 To 1000000
         Dim value As Double = rnd.NextDouble() * (upperBound - lowerBound) + lowerBound
         range(CInt(Math.Truncate((value - lowerBound) * 10))) += 1 
      Next
      
      For ctr As Integer = 0 To 9
         Dim lowerRange As Double = 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)
      Next 
   End Sub
End Module
' 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 %)

Создание случайных логических значенийGenerate random Boolean values

Класс не предоставляет методы, создающие Boolean значения. RandomThe Random class doesn't provide methods that generate Boolean values. Однако для этого можно определить собственный класс или метод.However, you can define your own class or method to do that. В следующем примере определяется класс BooleanGeneratorс одним NextBooleanметодом.The following example defines a class, BooleanGenerator, with a single method, NextBoolean. BooleanGenerator КлассRandom сохраняет объект как закрытую переменную.The BooleanGenerator class stores a Random object as a private variable. Метод вызывает метод иConvert.ToBoolean(Int32) передает результат в метод. Random.Next(Int32, Int32) NextBooleanThe NextBoolean method calls the Random.Next(Int32, Int32) method and passes the result to the Convert.ToBoolean(Int32) method. Обратите внимание, что в качестве аргумента используется 2, чтобы указать верхнюю границу случайного числа.Note that 2 is used as the argument to specify the upper bound of the random number. Так как это значение является эксклюзивным, вызов метода возвращает значение 0 или 1.Since this is an exclusive value, the method call returns either 0 or 1.

using namespace System;

public ref class BooleanGenerator
{
   private:
      Random^ rnd;

   public:
      BooleanGenerator()
      {
         rnd = gcnew Random();
      }

      bool NextBoolean()
      {
         return Convert::ToBoolean(rnd->Next(0, 2));
      }
};

void main()
{
   // Instantiate the Boolean generator.
   BooleanGenerator^ boolGen = gcnew 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));
}

// The example displays output like the following:
//       Number of true values:  500,004 (50.000 %)
//       Number of false values: 499,996 (50.000 %)
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 %)
Module Example
   Public Sub Main()
      ' Instantiate the Boolean generator.
      Dim boolGen As New BooleanGenerator()
      Dim totalTrue, totalFalse As Integer 
      
      ' Generate 1,0000 random Booleans, and keep a running total.
      For ctr As Integer = 0 To 9999999
          Dim value As Boolean = boolGen.NextBoolean()
          If value Then
             totalTrue += 1
          Else
             totalFalse += 1
          End If
      Next
      Console.WriteLine("Number of true values:  {0,7:N0} ({1:P3})", 
                        totalTrue, 
                        totalTrue/(totalTrue + totalFalse))
      Console.WriteLine("Number of false values: {0,7:N0} ({1:P3})", 
                        totalFalse, 
                        totalFalse/(totalTrue + totalFalse))
   End Sub                     
End Module

Public Class BooleanGenerator
   Dim rnd As Random
   
   Public Sub New()
      rnd = New Random()
   End Sub

   Public Function NextBoolean() As Boolean
      Return Convert.ToBoolean(rnd.Next(0, 2))
   End Function
End Class
' The example displays the following output:
'       Number of true values:  500,004 (50.000 %)
'       Number of false values: 499,996 (50.000 %)

Вместо создания отдельного класса для создания случайных Boolean значений в примере можно просто определить один метод.Instead of creating a separate class to generate random Boolean values, the example could simply have defined a single method. Однако Random в этом случае объект должен быть определен как переменная уровня класса, чтобы избежать создания экземпляра нового Random экземпляра в каждом вызове метода.In that case, however, the Random object should have been defined as a class-level variable to avoid instantiating a new Random instance in each method call. В Visual Basic случайный экземпляр может быть определен как статическая переменная в NextBoolean методе.In Visual Basic, the Random instance can be defined as a Static variable in the NextBoolean method. В следующем примере показана реализация.The following example provides an implementation.

using namespace System;

ref class Example
{
private:
   static Random^ rnd = gcnew Random();

public:
   static void Execute()
   {
      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));
   }

   static bool NextBoolean()
   {
      return Convert::ToBoolean(rnd->Next(0, 2));
   }
};

void main()
{
   Example::Execute();
}
// The example displays output like the following:
//       Number of true values:  499,777 (49.978 %)
//       Number of false values: 500,223 (50.022 %)
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 %)
Module Example
   Public Sub Main()
      Dim totalTrue, totalFalse As Integer 
      
      ' Generate 1,0000 random Booleans, and keep a running total.
      For ctr As Integer = 0 To 9999999
          Dim value As Boolean = NextBoolean()
          If value Then
             totalTrue += 1
          Else
             totalFalse += 1
          End If
      Next
      Console.WriteLine("Number of true values:  {0,7:N0} ({1:P3})", 
                        totalTrue, 
                        totalTrue/(totalTrue + totalFalse))
      Console.WriteLine("Number of false values: {0,7:N0} ({1:P3})", 
                        totalFalse, 
                        totalFalse/(totalTrue + totalFalse))
   End Sub 
                       
   Public Function NextBoolean() As Boolean
      Static rnd As New Random()
      Return Convert.ToBoolean(rnd.Next(0, 2))
   End Function
End Module
' The example displays the following output:
'       Number of true values:  499,777 (49.978 %)
'       Number of false values: 500,223 (50.022 %)

Создавать случайные 64-разрядные целые числаGenerate random 64-bit integers

Перегрузки Next метода возвращают 32-разрядные целые числа.The overloads of the Next method return 32-bit integers. Однако в некоторых случаях может потребоваться работать с 64-разрядными целыми числами.However, in some cases, you might want to work with 64-bit integers. Это можно сделать следующим образом:You can do this as follows:

  1. Вызовите NextDouble метод, чтобы получить значение двойной точности с плавающей запятой.Call the NextDouble method to retrieve a double-precision floating point value.

  2. Умножьте это значение на Int64.MaxValue.Multiply that value by Int64.MaxValue.

В следующем примере этот метод используется для создания 20 000 000 случайных длинных целых чисел и классификации их в 10 равных группах.The following example uses this technique to generate 20 million random long integers and categorizes them in 10 equal groups. Затем он вычисляет распределение случайных чисел, подчисляя число в каждой группе от 0 до Int64.MaxValue.It then evaluates the distribution of the random numbers by counting the number in each group from 0 to Int64.MaxValue. Как видно из выходных данных примера, числа распределяются более или реже по диапазону длинного целого числа.As the output from the example shows, the numbers are distributed more or less equally through the range of a long integer.

using namespace System;

void main()
{
   const Int64 ONE_TENTH = 922337203685477581;

   Random^ rnd = gcnew Random();
   Int64 number;
   array<int>^ count = gcnew array<int>(10);
   
   // Generate 20 million long integers.
   for (int ctr = 1; ctr <= 20000000; ctr++) {
      number = (Int64) (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 %
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 %
Module Example
   Public Sub Main()
      Const ONE_TENTH As Long = 922337203685477581

      Dim rnd As New Random()
      Dim number As Long
      Dim count(9) As Integer
      
      ' Generate 20 million long integers.
      For ctr As Integer = 1 To 20000000
         number = CLng(rnd.NextDouble() * Int64.MaxValue)
         ' Categorize random numbers.
         count(CInt(number \ ONE_TENTH)) += 1
      Next
      ' Display breakdown by range.
      Console.WriteLine("{0,28} {1,32}   {2,7}", "Range", "Count", "Pct.")
      Console.WriteLine()
      For ctr As Integer = 0 To 9
         Console.WriteLine("{0,25:N0}-{1,25:N0}  {2,8:N0}   {3,7:P2}", ctr * ONE_TENTH,
                            If(ctr < 9, ctr * ONE_TENTH + ONE_TENTH - 1, Int64.MaxValue), 
                            count(ctr), count(ctr)/20000000)
      Next
   End Sub
End Module
' 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 %

Альтернативный метод, использующий побитовую обработку, не создает действительно случайных чисел.An alternative technique that uses bit manipulation does not generate truly random numbers. Этот метод вызывает Next() метод для создания двух целых чисел, сдвига влево по одному на 32 бит и or их вместе.This technique calls Next() to generate two integers, left-shifts one by 32 bits, and ORs them together. Этот метод имеет два ограничения:This technique has two limitations:

  1. Поскольку бит 31 является битом знака, значение в битовом 31 полученного длинного целого числа всегда равно 0.Because bit 31 is the sign bit, the value in bit 31 of the resulting long integer is always 0. Это можно решить путем создания случайного значения 0 или 1, сдвига влево на 31 бит и индексами его с исходным произвольным целым числом.This can be addressed by generating a random 0 or 1, left-shifting it 31 bits, and ORing it with the original random long integer.

  2. Более серьезно, поскольку вероятность того, что значение, возвращаемое, Next() будет равно 0, будет несколько случайных чисел в диапазоне 0x0-0x00000000FFFFFFFF.More seriously, because the probability that the value returned by Next() will be 0, there will be few if any random numbers in the range 0x0-0x00000000FFFFFFFF.

Извлечение байтов в указанном диапазонеRetrieve bytes in a specified range

Перегрузки Next метода позволяют указать диапазон случайных чисел, NextBytes но метод — нет.The overloads of the Next method allow you to specify the range of random numbers, but the NextBytes method does not. В следующем примере реализуется NextBytes метод, который позволяет указать диапазон возвращаемых байтов.The following example implements a NextBytes method that lets you specify the range of the returned bytes. Он определяет Random2 класс, производный от Random , и перегружает его NextBytes метод.It defines a Random2 class that derives from Random and overloads its NextBytes method.

using namespace System;

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

   Random2(int seed) : Random(seed)
   {}

   void NextBytes(array<Byte>^ bytes, Byte minValue, Byte maxValue)
   {
      for (int ctr = bytes->GetLowerBound(0); ctr <= bytes->GetUpperBound(0); ctr++)
         bytes[ctr] = (Byte) Next(minValue, maxValue);
   }
};

void main()
{
    Random2^ rnd = gcnew Random2();
    array<Byte>^ bytes = gcnew array<Byte>(10000);
    array<int>^ total = gcnew array<int>(101);
    rnd->NextBytes(bytes, 0, 101);

    // Calculate how many of each value we have.
    for each (Byte 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();
    }
}
// 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
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
Module Example
   Public Sub Main()
       Dim rnd As New Random2()
       Dim bytes(9999) As Byte
       Dim total(100) As Integer
       rnd.NextBytes(bytes, 0, 101)
       
       ' Calculate how many of each value we have.
       For Each value In bytes
          total(value) += 1
       Next
       
       ' Display the results.
       For ctr As Integer = 0 To total.Length - 1
           Console.Write("{0,3}: {1,-3}   ", ctr, total(ctr))
           If (ctr + 1) Mod 5 = 0 Then Console.WriteLine()
       Next   
   End Sub
End Module

Public Class Random2 : Inherits Random
   Public Sub New()
      MyBase.New()
   End Sub   

   Public Sub New(seed As Integer)
      MyBase.New(seed)
   End Sub

   Public Overloads Sub NextBytes(bytes() As Byte, 
                                  minValue As Byte, maxValue As Byte)
      For ctr As Integer = bytes.GetLowerbound(0) To bytes.GetUpperBound(0)
         bytes(ctr) = CByte(MyBase.Next(minValue, maxValue))
      Next
   End Sub
End Class 
' 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

Метод создает оболочку Next(Int32, Int32) для вызова метода и задает минимальное значение, которое больше максимального значения (в данном случае 0 и 101), которое требуется вернуть в массив байтов. NextBytes(Byte[], Byte, Byte)The NextBytes(Byte[], Byte, Byte) method wraps a call to the Next(Int32, Int32) method and specifies the minimum value and one greater than the maximum value (in this case, 0 and 101) that we want returned in the byte array. Так как мы уверены, что целочисленные значения, возвращаемые Next методом, находятся в диапазоне Byte типа данных, мы можем безопасно привести их (в C#) или преобразовать их (в Visual Basic) из целых чисел в байты.Because we are sure that the integer values returned by the Next method are within the range of the Byte data type, we can safely cast them (in C#) or convert them (in Visual Basic) from integers to bytes.

Извлечение элемента из массива или коллекции в случайном порядкеRetrieve an element from an array or collection at random

Случайные числа часто используются в качестве индексов для получения значений из массивов или коллекций.Random numbers often serve as indexes to retrieve values from arrays or collections. Чтобы получить случайное значение индекса, можно вызвать Next(Int32, Int32) метод и использовать нижнюю границу массива в качестве значения его minValue аргумента, а на единицу больше, чем верхняя граница массива, в качестве значения его maxValue аргумента.To retrieve a random index value, you can call the Next(Int32, Int32) method, and use the lower bound of the array as the value of its minValue argument and one greater than the upper bound of the array as the value of its maxValue argument. Для массива, начинающегося с нуля, это эквивалентно его Length свойству или больше значения, возвращаемого Array.GetUpperBound методом.For a zero-based array, this is equivalent to its Length property, or one greater than the value returned by the Array.GetUpperBound method. В следующем примере случайным образом извлекается имя города в США из массива городов.The following example randomly retrieves the name of a city in the United States from an array of cities.

using namespace System;

void main()
{
   array<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 = gcnew 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
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
Module Example
   Public Sub Main()
      Dim cities() As String = { "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" }
      Dim rnd As New Random()
      Dim index As Integer = rnd.Next(0, cities.Length)
      Console.WriteLine("Today's city of the day: {0}",
                        cities(index))                           
   End Sub
End Module
' The example displays output like the following:
'   Today's city of the day: Honolulu

Извлечение уникального элемента из массива или коллекцииRetrieve a unique element from an array or collection

Генератор случайных чисел всегда может возвращать дублирующиеся значения.A random number generator can always return duplicate values. Так как диапазон чисел становится меньше или число формируемых значений становится больше, вероятность повторений растет.As the range of numbers becomes smaller or the number of values generated becomes larger, the probability of duplicates grows. Если случайные значения должны быть уникальными, создаются дополнительные числа для компенсации дубликатов, что приводит к ухудшению производительности.If random values must be unique, more numbers are generated to compensate for duplicates, resulting in increasingly poor performance.

Существует ряд методов для решения этого сценария.There are a number of techniques to handle this scenario. Одним из распространенных решений является создание массива или коллекции, содержащей значения для извлечения, и параллельный массив, содержащий случайные числа с плавающей запятой.One common solution is to create an array or collection that contains the values to be retrieved, and a parallel array that contains random floating-point numbers. Второй массив заполняется случайными числами во время создания первого массива, а Array.Sort(Array, Array) метод используется для сортировки первого массива с использованием значений в параллельном массиве.The second array is populated with random numbers at the time the first array is created, and the Array.Sort(Array, Array) method is used to sort the first array by using the values in the parallel array.

Например, если вы разрабатываете игру «косынка», необходимо убедиться, что каждая карта используется только один раз.For example, if you're developing a Solitaire game, you want to ensure that each card is used only once. Вместо создания случайных чисел для получения карты и отслеживания того, была ли карта уже обработана, можно создать параллельный массив случайных чисел, который можно использовать для сортировки колоды.Instead of generating random numbers to retrieve a card and tracking whether that card has already been dealt, you can create a parallel array of random numbers that can be used to sort the deck. После сортировки колоды приложение может поддерживать указатель, указывающий на индекс следующей карточки в колоде.Once the deck is sorted, your app can maintain a pointer to indicate the index of the next card on the deck.

Этот подход показан в приведенном ниже примере.The following example illustrates this approach. Он определяет Card класс, который представляет собой воспроизводимую карту Dealer , и класс, который обрабатывает колоду карточек с случайным перемещением.It defines a Card class that represents a playing card and a Dealer class that deals a deck of shuffled cards. Конструктор класса заполняет два массива deck : массив, имеющий область класса и представляющий все карты в колоде, и локальный order массив, deck имеющий то же количество элементов, что и массив, и заполняется Dealer со случайно сформированными Double значениями.The Dealer class constructor populates two arrays: a deck array that has class scope and that represents all the cards in the deck; and a local order array that has the same number of elements as the deck array and is populated with randomly generated Double values. Затем вызывается deckметоддля сортировки массива на основе значений в order массиве. Array.Sort(Array, Array)The Array.Sort(Array, Array) method is then called to sort the deck array based on the values in the order array.

using namespace System;

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

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

// A class that represents an individual card in a playing deck.
ref class Card
{
public:
   Suit Suit;
   FaceValue FaceValue;
   
   String^ ToString() override
   {
      return String::Format("{0:F} of {1:F}", this->FaceValue, this->Suit);
   }
};

ref class Dealer
{
private:
   Random^ rnd;
   // A deck of cards, without Jokers.
   array<Card^>^ deck = gcnew array<Card^>(52);
   // Parallel array for sorting cards.
   array<Double>^ order = gcnew array<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 = gcnew Random();
      // Initialize the deck.
      int deckCtr = 0;
      for each (auto suit in Enum::GetValues(Suit::typeid)) {
         for each (FaceValue faceValue in Enum::GetValues(FaceValue::typeid)) {
            Card^ card = gcnew 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);
   }

   array<Card^>^ Deal(int numberToDeal)
   {
      if (mustReshuffle) {
         Console::WriteLine("There are no cards left in the deck");
         return nullptr;
      }
      
      array<Card^>^ cardsDealt = gcnew array<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;
   }
};

void ShowCards(array<Card^>^ cards)
{
   for each (Card^ card in cards)
      if (card != nullptr)
         Console::WriteLine("{0} of {1}", card->FaceValue, card->Suit);
};

void main()
{
   Dealer^ dealer = gcnew Dealer();
   ShowCards(dealer->Deal(20));
}

// 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
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
' A class that represents an individual card in a playing deck.
Public Class Card
   Public Suit As Suit
   Public FaceValue As FaceValue
   
   Public Overrides Function ToString() As String
      Return String.Format("{0:F} of {1:F}", Me.FaceValue, Me.Suit)
   End Function
End Class

Public Enum Suit As Integer
   Hearts = 0
   Diamonds = 1
   Spades = 2
   Clubs = 3
End Enum

Public Enum FaceValue As Integer
   Ace = 1
   Two = 2
   Three = 3
   Four = 4
   Five = 5
   Six = 6
   Seven = 7
   Eight = 8
   Nine = 9
   Ten = 10
   Jack = 11
   Queen = 12
   King = 13
End Enum

Public Class Dealer
   Dim rnd As Random
   ' A deck of cards, without Jokers.
   Dim deck(51) As Card
   ' Parallel array for sorting cards.
   Dim order(51) As Double
   ' A pointer to the next card to deal.
   Dim ptr As Integer = 0
   ' A flag to indicate the deck is used.
   Dim mustReshuffle As Boolean
   
   Public Sub New()
      rnd = New Random()
      ' Initialize the deck.
      Dim deckCtr As Integer = 0
      For Each Suit In [Enum].GetValues(GetType(Suit))
         For Each faceValue In [Enum].GetValues(GetType(FaceValue))
            Dim card As New Card()
            card.Suit = CType(Suit, Suit)
            card.FaceValue = CType(faceValue, FaceValue)
            deck(deckCtr) = card  
            deckCtr += 1
         Next
      Next
      For ctr As Integer = 0 To order.Length - 1
         order(ctr) = rnd.NextDouble()   
      Next   
      Array.Sort(order, deck)
   End Sub

   Public Function Deal(numberToDeal As Integer) As Card()
      If mustReshuffle Then
         Console.WriteLine("There are no cards left in the deck")
         Return Nothing
      End If
      
      Dim cardsDealt(numberToDeal - 1) As Card
      For ctr As Integer = 0 To numberToDeal - 1
         cardsDealt(ctr) = deck(ptr)
         ptr += 1
         If ptr = deck.Length Then 
            mustReshuffle = True
         End If
         If mustReshuffle And ctr < numberToDeal - 1
            Console.WriteLine("Can only deal the {0} cards remaining on the deck.", 
                              ctr + 1)
            Return cardsDealt
         End If
      Next
      Return cardsDealt
   End Function
End Class

Public Module Example
   Public Sub Main()
      Dim dealer As New Dealer()
      ShowCards(dealer.Deal(20))
   End Sub
   
   Private Sub ShowCards(cards() As Card)
      For Each card In cards
         If card IsNot Nothing Then _
            Console.WriteLine("{0} of {1}", card.FaceValue, card.Suit)
      Next
   End Sub
End Module
' 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

Примечания для тех, кто наследует этот метод

В .NET Framework 1,0 и 1,1 — минимальная реализация класса, производного от Random обязательного Sample() переопределения метода для определения нового или измененного алгоритма создания случайных чисел.In the .NET Framework 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. Next()Производный класс может затем полагаться на реализацию базового класса методов Next(Int32, Int32), Next(Int32),, NextBytes(Byte[])и NextDouble() для вызова реализации Sample() метода производного класса.The derived class could then rely on the base class implementation of the Next(), Next(Int32), Next(Int32, Int32), NextBytes(Byte[]), and NextDouble() methods to call the derived class implementation of the Sample() method.

В .NET Framework 2,0 Next()и более поздних версиях поведение методов, Next(Int32, Int32)и NextBytes(Byte[]) изменилось, так что эти методы не Sample() обязательно вызывают реализацию производного класса метода.In the .NET Framework 2.0 and later, the behavior of the Next(), Next(Int32, Int32), and NextBytes(Byte[]) methods have changed so that these methods do not necessarily call the derived class implementation of the Sample() method. В результате классы, производные от Random класса, предназначенного для .NET Framework 2,0 и более поздних версий, также должны переопределять эти три метода.As a result, classes derived from Random that target the .NET Framework 2.0 and later should also override these three methods.

Примечания для тех, кто вызывает этот метод

Реализация генератора случайных чисел в Random классе не всегда остается одинаковой для основных версий .NET Framework.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. В результате не следует рассчитывать на то, что одно и то же начальное значение приведет к той же псевдо-случайной последовательности в разных версиях .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.

Конструкторы

Random() Random() Random() Random()

Инициализирует новый экземпляр класса Random с помощью зависимого от времени начального значения по умолчанию.Initializes a new instance of the Random class, using a time-dependent default seed value.

Random(Int32) Random(Int32) Random(Int32) Random(Int32)

Инициализирует новый экземпляр класса Random с помощью указанного начального значения.Initializes a new instance of the Random class, using the specified seed value.

Методы

Equals(Object) Equals(Object) Equals(Object) Equals(Object)

Определяет, равен ли заданный объект текущему объекту.Determines whether the specified object is equal to the current object.

(Inherited from Object)
GetHashCode() GetHashCode() GetHashCode() GetHashCode()

Служит хэш-функцией по умолчанию.Serves as the default hash function.

(Inherited from Object)
GetType() GetType() GetType() GetType()

Возвращает объект Type для текущего экземпляра.Gets the Type of the current instance.

(Inherited from Object)
MemberwiseClone() MemberwiseClone() MemberwiseClone() MemberwiseClone()

Создает неполную копию текущего объекта Object.Creates a shallow copy of the current Object.

(Inherited from Object)
Next() Next() Next() Next()

Возвращает неотрицательное случайное целое число.Returns a non-negative random integer.

Next(Int32) Next(Int32) Next(Int32) Next(Int32)

Возвращает неотрицательное случайное целое число, которое меньше указанного максимального значения.Returns a non-negative random integer that is less than the specified maximum.

Next(Int32, Int32) Next(Int32, Int32) Next(Int32, Int32) Next(Int32, Int32)

Возвращает случайное целое число в указанном диапазоне.Returns a random integer that is within a specified range.

NextBytes(Byte[]) NextBytes(Byte[]) NextBytes(Byte[]) NextBytes(Byte[])

Заполняет элементы указанного массива байтов случайными числами.Fills the elements of a specified array of bytes with random numbers.

NextBytes(Span<Byte>) NextBytes(Span<Byte>) NextBytes(Span<Byte>) NextBytes(Span<Byte>)
NextDouble() NextDouble() NextDouble() NextDouble()

Возвращает случайное число с плавающей запятой, которое больше или равно 0,0 и меньше 1,0.Returns a random floating-point number that is greater than or equal to 0.0, and less than 1.0.

Sample() Sample() Sample() Sample()

Возвращает случайное число с плавающей запятой в диапазоне от 0,0 до 1,0.Returns a random floating-point number between 0.0 and 1.0.

ToString() ToString() ToString() ToString()

Возвращает строку, представляющую текущий объект.Returns a string that represents the current object.

(Inherited from Object)

Применяется к