Random Класс
Некоторые сведения относятся к предварительной версии продукта, в которую до выпуска могут быть внесены существенные изменения. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.
Представляет генератор псевдослучайных чисел, то есть алгоритм, который генерирует последовательность чисел, отвечающую определенным статистическим критериям случайности.
Примеры
В следующем примере создается один генератор случайных чисел и вызывается его NextBytesNextметоды и NextDouble методы для создания последовательностей случайных чисел в разных диапазонах.
В следующем примере создается случайное целое число, которое используется в качестве индекса для получения строкового значения из массива.
Комментарии
Псевдослучайные числа выбираются с одинаковой вероятностью из конечного набора чисел. Выбранные числа не являются полностью случайными, так как математический алгоритм используется для их выбора, но они достаточно случайны для практических целей. Текущая реализация Random класса основана на измененной версии алгоритма генератора случайных чисел Дональда Э. Кнута. Дополнительные сведения см. в разделе D. E. Кнут. Искусство компьютерного программирования, том 2: полунумерные алгоритмы. Аддисон-Уэсли, Рединг, MA, третий выпуск, 1997.
Чтобы создать криптографически безопасное случайное число, например случайное число, подходящее для создания случайного пароля, используйте RNGCryptoServiceProvider класс или наследуйте класс.System.Security.Cryptography.RandomNumberGenerator
Создание экземпляра генератора случайных чисел
Вы создаете экземпляр генератора случайных чисел, предоставляя начальное значение (начальное значение для алгоритма создания псевдослучайного числа) конструктору Random класса. Начальное значение можно указать явным или неявным образом:
Конструктор Random(Int32) использует явное начальное значение, которое вы предоставляете.
Конструктор Random() использует начальное значение по умолчанию. Это наиболее распространенный способ создания экземпляра генератора случайных чисел.
В платформа .NET Framework начальное значение по умолчанию зависит от времени. В .NET Core начальное значение по умолчанию создается генератором псевдослучайных чисел.
Если одно начальное значение используется для отдельных Random объектов, они будут создавать одинаковые ряды случайных чисел. Это может быть полезно для создания набора тестов, обрабатывающего случайные значения, или для воспроизведения игр, которые являются производными от случайных чисел. Однако обратите внимание, что Random объекты в процессах, выполняющихся в разных версиях платформа .NET Framework, могут возвращать разные ряды случайных чисел, даже если они создаются с одинаковыми начальными значениями.
Чтобы создать различные последовательности случайных чисел, можно сделать начальное значение зависимым от времени, тем самым создавая разные ряды с каждым новым экземпляром Random. Параметризованный Random(Int32) конструктор может принимать Int32 значение на основе числа тактов в текущее время, тогда как конструктор без Random() параметров использует системные часы для создания начального значения. Однако только на платформа .NET Framework, так как часы имеют конечное разрешение, используя конструктор без параметров для создания различных Random объектов в близком последовательности, создаются генераторы случайных чисел, которые создают идентичные последовательности случайных чисел. В следующем примере показано, как два Random объекта, созданные при близком последовательности в приложении платформа .NET Framework, создают идентичный ряд случайных чисел. В большинстве систем Windows объекты, созданные в течение 15 миллисекундах друг друга, скорее всего, Random будут иметь одинаковые начальные значения.
Чтобы избежать этой проблемы, создайте один Random объект вместо нескольких объектов. Обратите внимание, что класс Random в .NET Core не имеет этого ограничения.
Предотвращение нескольких экземпляров
На платформа .NET Framework инициализация двух генераторов случайных чисел в жестком цикле или в быстром последовательности создает два генератора случайных чисел, которые могут создавать идентичные последовательности случайных чисел. В большинстве случаев это не является намерением разработчика и может привести к проблемам с производительностью, так как создание экземпляра и инициализация генератора случайных чисел является относительно дорогостоящим процессом.
Чтобы повысить производительность и избежать случайного создания отдельных генераторов случайных чисел, создающих идентичные числовые последовательности, рекомендуется создать один Random объект для создания множества случайных чисел с течением времени вместо создания новых Random объектов для создания одного случайного числа.
Random Однако класс не является потокобезопасным. При вызове Random методов из нескольких потоков следуйте рекомендациям, описанным в следующем разделе.
Класс System.Random и безопасность потоков
Вместо создания экземпляров отдельных Random объектов рекомендуется создать один Random экземпляр для создания всех случайных чисел, необходимых приложению. Random Однако объекты не являются потокобезопасным. Если приложение вызывает Random методы из нескольких потоков, необходимо использовать объект синхронизации, чтобы одновременно получить доступ только к одному потоку. Если вы не гарантируете, что Random доступ к объекту осуществляется потокобезопасно, вызовы методов, возвращающих случайные числа, возвращают 0.
В следующем примере используется оператор блокировки C#, функция блокировки F# и оператор Visual Basic SyncLock, чтобы обеспечить доступ к одному генератору случайных чисел 11 потоков в потокобезопасном режиме. Каждый поток создает 2 миллиона случайных чисел, подсчитывает количество созданных случайных чисел и вычисляет их сумму, а затем обновляет итоговые значения для всех потоков после завершения выполнения.
В этом примере обеспечивается потокобезопасность следующими способами:
Атрибут ThreadStaticAttribute используется для определения локальных переменных потока, которые отслеживают общее число созданных случайных чисел и их сумму для каждого потока.
Блокировка lock (инструкция в C#, lock функция в F# и SyncLock инструкция в Visual Basic) защищает доступ к переменным для общего количества и суммы всех случайных чисел, созданных во всех потоках.
Семафор ( CountdownEvent объект) используется для обеспечения блокировок основного потока до завершения выполнения всех остальных потоков.
В примере проверяется, поврежден ли генератор случайных чисел, определив, возвращаются ли два последовательных вызова методов создания случайных чисел 0. При обнаружении повреждения в примере объект используется CancellationTokenSource для сигнала о том, что все потоки должны быть отменены.
Перед созданием каждого случайного CancellationToken числа каждый поток проверяет состояние объекта. Если запрашивается отмена, в примере вызывается CancellationToken.ThrowIfCancellationRequested метод для отмены потока.
Следующий пример идентичен первому, за исключением того, что он использует Task объект и лямбда-выражение вместо Thread объектов.
Он отличается от первого примера следующими способами:
Переменные для отслеживания числа случайных чисел и их суммы в каждой задаче являются локальными для задачи, поэтому не нужно использовать ThreadStaticAttribute атрибут.
Статический Task.WaitAll метод используется для обеспечения того, чтобы основной поток не завершился до завершения всех задач. Объекту не требуется CountdownEvent .
Исключение, которое приводит к отмене задачи, отображается в методе Task.WaitAll . В предыдущем примере он обрабатывается каждым потоком.
Создание различных типов случайных чисел
Генератор случайных чисел предоставляет методы, позволяющие создавать следующие типы случайных чисел:
Ряд значений Byte . Количество байтовых значений определяется путем передачи массива, инициализированного количеству элементов, которые нужно вернуть методу NextBytes . В следующем примере создается 20 байт.
Одно целое число. Можно выбрать, требуется ли целое число от 0 до максимального значения (Int32.MaxValue –1), вызвав Next() метод, целое число от 0 до определенного значения, вызвав Next(Int32) метод или целое число в диапазоне значений путем вызова Next(Int32, Int32) метода. В параметризованных перегрузках указанное максимальное значение является эксклюзивным; то есть фактическое максимальное число, созданное, меньше указанного значения.
В следующем примере вызывается Next(Int32, Int32) метод для создания 10 случайных чисел от –10 до 10. Обратите внимание, что второй аргумент метода задает монопольную верхнюю границу диапазона случайных значений, возвращаемых методом. Другими словами, наибольшее целое число, которое может возвращать метод, меньше этого значения.
Одно значение с плавающей запятой от 0,0 до меньше 1,0 путем вызова NextDouble метода. Исключаемая верхняя граница случайного числа, возвращаемого методом, — 1, поэтому его фактическая верхняя граница — 0,999999999999978. В следующем примере создается 10 случайных чисел с плавающей запятой.
Этот Next(Int32, Int32) метод позволяет указать диапазон возвращаемого случайного числа. maxValue Однако параметр, указывающий возвращаемый верхний диапазон, является эксклюзивным, а не инклюзивным значением. Это означает, что вызов Next(0, 100) метода возвращает значение от 0 до 99, а не от 0 до 100.
Подстановка собственного алгоритма
Вы можете реализовать собственный генератор случайных чисел, наследуя от Random класса и предоставляя алгоритм создания случайных чисел. Для предоставления собственного алгоритма необходимо переопределить Sample метод, который реализует алгоритм создания случайных чисел. Кроме того, Next(Int32, Int32)следует переопределить Next()методы и NextBytes методы, чтобы убедиться, что они вызывают переопределенный Sample метод. Вам не нужно переопределять Next(Int32) методы и NextDouble методы.
Пример, производный Random от класса и изменяющий генератор псевдослучайных чисел по умолчанию, см. на Sample странице ссылки.
Как использовать System.Random для.
В следующих разделах рассматриваются и предоставляются примеры кода для некоторых способов использования случайных чисел в приложении.
Получение той же последовательности случайных значений
Иногда требуется создать ту же последовательность случайных чисел в сценариях тестирования программного обеспечения и в игре. Тестирование с той же последовательностью случайных чисел позволяет обнаруживать регрессии и проверять исправления ошибок. Использование той же последовательности случайных чисел в играх позволяет воспроизвести предыдущие игры.
Вы можете создать ту же последовательность случайных чисел, указав одно начальное значение конструктору Random(Int32) . Начальное значение предоставляет начальное значение для алгоритма псевдослучайного формирования чисел. В следующем примере используется значение 100100 в качестве произвольного начального значения для создания экземпляра Random объекта, отображается 20 случайных значений с плавающей запятой и сохраняется начальное значение. Затем он восстанавливает начальное значение, создает экземпляр нового генератора случайных чисел и отображает те же 20 случайных значений с плавающей запятой. Обратите внимание, что в примере могут возникать разные последовательности случайных чисел, если они выполняются в разных версиях платформа .NET Framework.
Получение уникальных последовательностей случайных чисел
Предоставление различных начальных значений экземплярам класса приводит к тому, что каждый генератор случайных Random чисел создает другую последовательность значений. Начальное значение можно указать явным образом, вызвав Random(Int32) конструктор или неявно вызвав Random() конструктор. Большинство разработчиков вызывают конструктор без параметров, который использует системные часы. В следующем примере используется этот подход для создания экземпляров двух Random экземпляров. Каждый экземпляр отображает ряд из 10 случайных целых чисел.
Однако из-за ограниченного разрешения системные часы не обнаруживают различия времени, которые меньше 15 миллисекунд. Таким образом, если код вызывает перегрузку Random() платформа .NET Framework для создания экземпляра двух Random объектов в последовательности, вы можете случайно предоставить объектам одинаковые начальные значения. (Класс Random в .NET Core не имеет этого ограничения.) Чтобы увидеть это в предыдущем примере, закомментируйте Thread.Sleep вызов метода и скомпилируйте и запустите пример еще раз.
Чтобы предотвратить это, рекомендуется создать экземпляр одного Random объекта, а не несколько. Тем не менее, так как Random не является потокобезопасной, необходимо использовать некоторое устройство синхронизации, если вы обращаетесь к экземпляру Random из нескольких потоков. Дополнительные сведения см. в разделе "Случайный класс" и "Безопасность потоков " ранее в этом разделе. Кроме того, можно использовать механизм задержки, например Sleep метод, используемый в предыдущем примере, чтобы гарантировать, что экземпляры выполняются более чем в 15 миллисекундах.
Получение целых чисел в указанном диапазоне
Вы можете получить целые числа в указанном диапазоне, вызвав Next(Int32, Int32) метод, который позволяет указать как нижнюю, так и верхнюю границу чисел, возвращаемых генератором случайных чисел. Верхняя граница является монопольным, а не инклюзивным значением. То есть он не включается в диапазон значений, возвращаемых методом. В следующем примере этот метод используется для создания случайных целых чисел от -10 до 10. Обратите внимание, что он задает значение 11, которое больше требуемого значения в качестве значения аргумента maxValue в вызове метода.
Получение целых чисел с указанным числом цифр
Вы можете вызвать Next(Int32, Int32) метод для получения чисел с указанным числом цифр. Например, чтобы получить числа с четырьмя цифрами (т. е. числа, которые варьируются от 1000 до 9999), метод вызывается Next(Int32, Int32) со minValue значением 1000 и maxValue значением 10000, как показано в следующем примере.
Получение значений с плавающей запятой в указанном диапазоне
Метод NextDouble возвращает случайные значения с плавающей запятой, которые варьируются от 0 до меньше 1. Однако часто требуется создать случайные значения в каком-то другом диапазоне.
Если интервал между минимальным и максимальным требуемым значениями равен 1, можно добавить разницу между требуемым начальным интервалом и 0 к числу, возвращаемого методом NextDouble . В следующем примере создается 10 случайных чисел от -1 до 0.
Чтобы создать случайные числа с плавающей запятой, нижняя граница которых равна 0, но верхняя граница больше 1 (или, в случае отрицательных чисел, нижняя граница которых меньше -1 и верхняя граница равна 0), умножьте случайное число на ненулевое. В следующем примере создается 20 миллионов случайных чисел с плавающей запятой, которые варьируются от 0 до Int64.MaxValue. Также отображается распределение случайных значений, созданных методом.
Чтобы создать случайные числа с плавающей запятой между двумя произвольными значениями, например Next(Int32, Int32) методом для целых чисел, используйте следующую формулу:
В следующем примере создается 1 миллион случайных чисел, которые варьируются от 10,0 до 11,0 и отображают их распределение.
Создание случайных логических значений
Класс Random не предоставляет методы, которые создают Boolean значения. Однако для этого можно определить собственный класс или метод. В следующем примере определяется класс с BooleanGenerator одним методом NextBoolean . Класс BooleanGenerator сохраняет Random объект в виде частной переменной. Метод NextBoolean вызывает Random.Next(Int32, Int32) метод и передает результат методу Convert.ToBoolean(Int32) . Обратите внимание, что 2 используется в качестве аргумента для указания верхней границы случайного числа. Так как это эксклюзивное значение, вызов метода возвращает значение 0 или 1.
Вместо создания отдельного класса для создания случайных Boolean значений пример может просто определить один метод. Однако в этом случае объект должен быть определен как переменная уровня класса, Random чтобы избежать создания экземпляра нового Random экземпляра в каждом вызове метода. В Visual Basic случайный экземпляр можно определить как статическую переменную в методе NextBoolean . В следующем примере представлена реализация.
Создание случайных 64-разрядных целых чисел
Перегрузки Next метода возвращают 32-разрядные целые числа. Однако в некоторых случаях может потребоваться работать с 64-разрядными целыми числами. Это можно сделать следующим образом:
NextDouble Вызовите метод, чтобы получить значение двойной точности с плавающей запятой.
Умножьте это значение на Int64.MaxValue.
В следующем примере используется этот метод для создания 20 миллионов случайных целых чисел и классификации их в 10 равных группах. Затем он вычисляет распределение случайных чисел, подсчитывая число в каждой группе от 0 до Int64.MaxValue. Как показано в выходных данных из примера, числа распределяются более или менее равномерно по диапазону длинного целого числа.
Альтернативный метод, использующий битовое манипулирование, не создает действительно случайные числа. Этот метод вызывает Next() создание двух целых чисел, сдвигов влево на 32 бита и OR их вместе. Этот метод имеет два ограничения:
Так как бит 31 является битом знака, значение в бите 31 результирующего длинного целого числа всегда равно 0. Это можно решить, создав случайное значение 0 или 1, сместив его влево 31 бит, и ORing его с исходным случайным длинным целым числом.
Более серьезно, поскольку вероятность того, что возвращаемое Next() значение будет равно 0, будет несколько, если какие-либо случайные числа в диапазоне 0x0-0x00000000FFFFFFFF.
Получение байтов в указанном диапазоне
Перегрузки Next метода позволяют указать диапазон случайных чисел, но NextBytes метод не делает. В следующем примере реализуется NextBytes метод, который позволяет указать диапазон возвращаемых байтов. Он определяет класс, производный Random2 от Random метода и перегружающий его NextBytes метод.
Метод NextBytes(Byte[], Byte, Byte) заключает вызов Next(Int32, Int32) метода и задает минимальное значение и больше максимального значения (в данном случае 0 и 101), которые мы хотим вернуть в массив байтов. Так как мы уверены, что целые значения, возвращаемые методомNext, находятся в диапазоне Byte типа данных, мы можем безопасно привести их (в C# и F#) или преобразовать их (в Visual Basic) из целых чисел в байты.
Получение элемента из массива или коллекции случайным образом
Случайные числа часто служат индексами для получения значений из массивов или коллекций. Чтобы получить случайное значение индекса, можно вызвать Next(Int32, Int32) метод и использовать нижнюю границу массива в качестве значения его minValue аргумента и один больше верхней границы массива в качестве значения аргумента maxValue . Для массива, отсчитываемого от нуля, это эквивалентно его Length свойству или одному больше, чем значение, возвращаемое методом Array.GetUpperBound . В следующем примере случайным образом извлекается имя города в США из массива городов.
Получение уникального элемента из массива или коллекции
Генератор случайных чисел всегда может возвращать повторяющиеся значения. По мере того как диапазон чисел становится меньше или число созданных значений становится больше, вероятность дублирования увеличивается. Если случайные значения должны быть уникальными, для компенсации дубликатов создается больше чисел, что приводит к увеличению производительности.
Существует ряд методов для обработки этого сценария. Одним из распространенных решений является создание массива или коллекции, содержащей извлекаемые значения, и параллельный массив, содержащий случайные числа с плавающей запятой. Второй массив заполняется случайными числами во время создания первого массива, а Array.Sort(Array, Array) метод используется для сортировки первого массива с помощью значений в параллельном массиве.
Например, если вы разрабатываете игру Solitaire, необходимо убедиться, что каждая карточка используется только один раз. Вместо создания случайных чисел для получения карточки и отслеживания того, была ли эта карта уже выполнена, можно создать параллельный массив случайных чисел, который можно использовать для сортировки колоды. После сортировки колоды ваше приложение может сохранить указатель, чтобы указать индекс следующей карточки на палубе.
Этот подход показан в приведенном ниже примере. Он определяет Card класс, представляющий игровой карты и Dealer класс, который сделок с колодой перетасованными картами. Dealer Конструктор класса заполняет два массива: deck массив, имеющий область класса и представляющий все карточки в колоде, а также локальный order массив с таким же количеством элементов, что deck и массив и заполняется случайным образом созданными Double значениями. Затем Array.Sort(Array, Array) вызывается метод для сортировки массива deck на основе значений в массиве order .
Примечания для тех, кто наследует этот метод
В платформа .NET Framework 1.0 и 1.1 минимальная реализация класса, производного от Random обязательного переопределения Sample() метода для определения нового или измененного алгоритма для создания случайных чисел. Затем производный класс может полагаться на реализацию Next()базового класса метода , Next(Int32)Next(Int32, Int32), NextBytes(Byte[])и NextDouble() методы для вызова реализации производного Sample() класса метода.
В платформа .NET Framework 2.0 и более поздних версий поведение Next()Next(Int32, Int32)NextBytes(Byte[]) методов изменилось, чтобы эти методы не обязательно вызывали реализацию производного Sample() класса метода. В результате классы, производные от этого, предназначены для Random платформа .NET Framework 2.0 и более поздних версий, также должны переопределять эти три метода.
Примечания для тех, кто вызывает этот метод
Реализация генератора случайных чисел в Random классе не гарантируется, что они остаются неизменными в основных версиях платформа .NET Framework. В результате вы не должны предполагать, что одно и то же начальное значение приведет к тому же псевдослучайной последовательности в разных версиях платформа .NET Framework.
Конструкторы
Инициализирует новый экземпляр класса Random, используя начальное значение по умолчанию.
Инициализирует новый экземпляр класса Random с помощью указанного начального значения.
Свойства
Предоставляет потокобезопасный Random экземпляр, который может использоваться одновременно из любого потока.
Методы
Определяет, равен ли указанный объект текущему объекту.
Служит хэш-функцией по умолчанию.
Возвращает объект Type для текущего экземпляра.
Создает неполную копию текущего объекта Object.
Возвращает неотрицательное случайное целое число.
Возвращает неотрицательное случайное целое число, которое меньше указанного максимального значения.
Возвращает случайное целое число в указанном диапазоне.
Заполняет элементы указанного массива байтов случайными числами.
Заполняет элементы указанного диапазона байтов случайными числами.
Возвращает случайное число с плавающей запятой, которое больше или равно 0,0 и меньше 1,0.
Возвращает неотрицательное случайное целое число.
Возвращает неотрицательное случайное целое число, которое меньше указанного максимального значения.
Возвращает случайное целое число в указанном диапазоне.
Возвращает случайное число с плавающей запятой, которое больше или равно 0,0 и меньше 1,0.
Возвращает случайное число с плавающей запятой в диапазоне от 0,0 до 1,0.
Как вы генерируете случайные строки в C++?
Я ищу методы для генерации случайных строк в C++.Вот мой код:
но seed(time(NULL)) не является достаточно случайным.Есть ли другой лучший способ генерировать случайные строки в C++?
6 ответов
не называй srand() на каждом вызове функции-только вызовите его один раз при первом вызове функции или запуске программы. Вы migh хотите иметь флаг, указывающий, является ли srand() уже назвали.
засахаренный метод хорош, за исключением того, что вы злоупотребляете srand() и получить предсказуемо плохие результаты.
можно использовать импульс.Random. Она использует другой генератор, чем с большинством стандартных библиотек, которые должны быть более надежными.
в частности, большинство стандартных библиотек предоставляют линейные конгруэнтные генераторы, которые не очень хорошо работают, когда вы mod их результаты с небольшими числами. Повышение.У рэндома есть генератор Mersenne twister.
Как говорит sharptooth, хотя (хорошее пятно!), только посеять генератор один раз, в самом начале ваша программа. Засев его каждый раз, когда вы хотите что-то случайное, контрпродуктивно.
сделайте интерфейс, чтобы получить случайное число на этом сайтеhttp://www.random.org/ и вы обязательно получите реальное случайное число! Но если вы ищете производительность.
в системах unix вы можете читать случайные значения из файла /dev/random
Если вы предпочитаете использовать стандартную библиотеку, то вы можете сделать что-то вроде этого:
этот код, естественно, более модульный, и стандартные сопровождающие библиотеки, как правило, пишут лучший код, чем я. Таким образом, я могу изменить случайный символ, генерирующий часть кода, не касаясь ничего другого. Я мог бы даже переслать функцию, которая случайным образом выбирает генератор случайных чисел! Не то чтобы это усугубляло случайность или что-то в этом роде.
используйте std:: generate_n. Таким образом, вы можете указать длину сгенерированной строки. В приведенном ниже случае его 4.
Урок #5 — Генератор чисел и работа со строками
Для генерации случайных чисел необходимо использовать метод rand() . Чтобы создать случайное число в диапазоне от 1 до 20 потребуется следующий код:
При использовании такого кода число будет генерироваться случайны образом, но всегда будет неизменным. Чтобы каждый раз при запуске программы выводилось новое случайное число необходимо использовать библиотеку: #include <time.h> . После её подключения в функции main пропишите команду: srand(time(NULL)); .
Функции для строк
Для работы со строками необходимо подключить библиотеку #include <string> .
Для получения целой строки от пользователя используйте функцию «getline(cin, value)». В функции параметр value является названием переменной, в которую будет записано значение от пользователя.