Как сгенерировать случайное число в си шарп
- Главная
- C#
- Базовый курс C#
- Глава 1. Самое начало
- Глава 2. Основы ООП
- Глава 3. WinFroms
- Начало
- Окружение
- Структура программы
- Основы синтаксиса
- Типы данных
- Преобразование типов данных
- C#
- Алгоритмы
- Всякая всячина…
- Обучающий материал
- Практикум
- Технические новости сайта
Генерация случайных чисел в C#
Доброго времени суток! Эта статья носит практический характер и в ней я расскажу о том, как использовать генератор случайных чисел в C# и для чего это Вам может пригодиться. Хотя, если на чистоту, то речь пойдет о генераторе псевдослучайных чисел…
Где нам могут понадобиться случайные числа, да на самом деле можно привести в пример много случаев, например, криптография, или механизмы разрешения различных коллизий. Поверьте, рано или поздно Вам с такой необходимостью придется столкнуться, если уже не пришлось, раз читаете эту статью. К счастью, в C# генератор случайных чисел разработан до нас, и единственное что нам нужно будет, большинстве случаев, это просто правильно им пользоваться. И так, для генерации случайных чисел в программах, написанных на C#, предназначен класс «Random».
//Создание объекта для генерации чисел Random rnd = new Random(); //Получить очередное (в данном случае - первое) случайное число int value = rnd.Next(); //Вывод полученного числа в консоль Console.WriteLine(value);
Как видите — ничего сложного! Сначала создаем объект типа «Random», потом вызываем его метод «Next», в результате чего и получаем случайное число. Если мы вызовем метод «Next» несколько раз, то получим разные числа. Такой код, даст нам четыре разных, случайных числа:
//Создание объекта для генерации чисел Random rnd = new Random(); int value = rnd.Next(); //Получить очередное случайное число int value1 = rnd.Next(); //Получить очередное случайное число int value2 = rnd.Next(); //Получить очередное случайное число int value3 = rnd.Next(); //Получить очередное случайное число Console.WriteLine(value); //Вывод числа в консоль Console.WriteLine(value1); //Вывод числа в консоль Console.WriteLine(value2); //Вывод числа в консоль Console.WriteLine(value3); //Вывод числа в консоль
А теперь, давайте слегка усложним задачу, представим, что нам нужно получить случайное число в определенном диапазоне. Но и эта задача выполняется довольно просто:
//Создание объекта для генерации чисел Random rnd = new Random(); //Получить случайное число (в диапазоне от 0 до 10) int value = rnd.Next(0, 10); //Вывод числа в консоль Console.WriteLine(value);
Как видите, и это выполняется несложно! Для этого мы всего лишь вызвали метод «Next» с двумя параметрами, первый из которых обозначает нижнюю границу диапазона, а второй — верхнюю.
Кстати, ограничить можно только верхнюю границу диапазона, для этого нужно вызвать метод «Next» с одним параметром, который и будет обозначать верхнюю границу.
Но это ещё не всё, есть еще один важный нюанс, на самом деле генератор случайных чисел является генератором псевдослучайных чисел, т.е. числа, которые он возвращает, не являются чисто случайными, они «вырабатываются» по определенным и четким законам, а «случайность» зависит от инициализации объекта, который генерирует числа (объекта класса «Random»). В примерах, приведенных выше, мы использовали конструктор по умолчанию, и в таком случае (судя по всему), «начальное значение» задается системой, и на основании системного времени. Но мы может задавать это самое «начальное значение» и сами:
//Создание объекта для генерации чисел (с указанием начального значения) Random rnd = new Random(245); //Получить случайное число int value = rnd.Next();
Только обратите внимание, начальное значение используется для генерации чисел, а не для возвращения первого числа, т.е. первое сгенерированное число не будет тем, что указано при создании объекта.
Так вот если два (или более) разных объекта класса «Random» будут одинаково проинициализированы, то и возвращать они будут одни и те же числа, например, следующий код, выведет в консоль три одинаковых числа:
class Program < //Этот метод должен возвращать случайное значение static int GetRandom() < //Создание объекта для генерации чисел (с указанием начального значения) Random rnd = new Random(245); //Получить случайное число int value = rnd.Next(); //Вернуть полученное значение return value; >static void Main(string[] args) < //Вывод сгенерированных чисел в консоль Console.WriteLine(GetRandom()); Console.WriteLine(GetRandom()); Console.WriteLine(GetRandom()); >>
Как видите, не смотря на то, что в при каждом вызове метода «GetRandom» создается новый объект для генерации случайных чисел, инициализируются эти объекты одним и тем же значением. Так что, будьте внимательны!
C# — Генерация случайного числа


Если Вам подходит генерация псевдо-случайных чисел, можно воспользоваться классом Random. При создании более одного случайного числа все же предпочтительно создать один раз экземпляр класса Random, и потом генерировать новые значения с помощью метода random.Next(). Потому что если между созданиями экземпляров класса будет небольшой промежуток времени у Вас будут повторяющиеся случайные чисел.
Рассмотрим несколько примеров:
Random rnd = new Random(); int randomNumber1 = random.Next(); int randomNumber2 = rnd.Next(1, 6); // генерация случайного чисела от 1 до 5 int randomNumber3 = rnd.Next(91); // генерация случайного чисела от 0 до 90Code language: JavaScript (javascript)Для генерации «безопасных» случайных чисел нам нужно использовать класс RNGCryptoServiceProvider.
Рассмотрим пример использования.
using System.Security.Cryptography; . using (var generatorProvider = new RNGCryptoServiceProvider()) < var data = new byte[4]; // 4 для int32 generatorProvider.GetBytes(data); var randomValue = BitConverter.ToInt32(data, 0); >Code language: JavaScript (javascript)PS: Если вы хотите сгенерировать случайное значение в Unity, Вам нужно проверить чтобы использовалось правильные пространство имен, а именно System.Random, потому что в Unity есть UnityEngine.Random, в котором нет возможности генерировать случайные значения.
Похожие темы:
- Visual Studio — использование пакетов из nuget.org
- Visual Studio package did not load correctly
- Как изменить язык интерфейса Visual Studio 2019 (после установки)
- Перебор елементов перечисления в цикле
- Как отключить CodeLens
- C# — The host localhost does not support SSL connections.
Генерация случайных чисел в C#
уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.
Генерация случайных чисел является неотъемлемой и важной частью многих криптографических операций. Например, криптографические ключи должны выбираться настолько случайно, насколько это, в принципе, возможно. В .NET C# есть несколько вариантов генерации случайных чисел.
Класс Random
Этот класс представляет генератор псевдослучайных чисел. То есть, в работе этого класса заложен алгоритм, который генерирует последовательность чисел, отвечающую определенным статистическим критериям случайности.
Конструкторы класса Random
У класса определено два конструктора. Первый конструктор — без параметров, создает новый экземпляр класса и инициализирует его значением по умолчанию. В .NET Framework начальное значение по умолчанию зависит от текущего времени. В .NET Core и более поздних версиях платформы начальное значение по умолчанию создается генератором псевдослучайных чисел потока. Конструктор без параметров используется наиболее часто и позволяет создавать генераторы случайных чисел с оптимальной производительностью и вероятностью распределения случайной величины. Например, так мы можем создать экземпляр Random , используя этот конструктор:
Random rnd1 = new Random();
Второй конструктор позволяет создавать новый экземпляр Random и инициализировать его заданным значением, например
Random rnd1 = new Random(100);
Этот конструктор стоит использовать в том случае, если Вам необходимо получать каждый раз одну и ту же серию псевдослучайных чисел, например, для отладки приложения. Чтобы продемонстрировать наглядно, что имеется в виду, напишем следующий пример:
byte[] bytes1 = new byte[5]; Random rnd1 = new Random(); rnd1.NextBytes(bytes1); for (int ctr = bytes1.GetLowerBound(0); ctr ", bytes1[ctr]); if ((ctr + 1) % 10 == 0) Console.WriteLine(); >
здесь мы создаем массив из пяти псевдослучайных байтов и выводим его в консоль. Вот, что мы можем увидеть, если перезапустим наше приложение, скажем, 3 раза:
207 1 36 222 242
32 16 142 152 22
89 87 143 31 161Три запуска — три различных серии случайных чисел. Теперь воспользуемся конструктором с начальным значением и также попытаемся сформировать три серии случайных чисел:
Random rnd1 = new Random(100); //тут тот же код, что и в примере выше
26 86 40 240 54
26 86 40 240 54
26 86 40 240 54Три запуска — три серии одинаковых чисел.
Вот, собственно, наглядная демонстрация того, чем принципиально отличаются конструкторы у Random .
Методы и свойства Random
Чтобы сгенерировать случайное число, у класса Random предусмотрены следующие методы:
Метод Описание Next() Возвращает неотрицательное случайное целое число. Next(Int32) Возвращает неотрицательное случайное целое число, которое меньше указанного максимального значения. Next(Int32, Int32) Возвращает случайное целое число в указанном диапазоне. Next Bytes(Byte[]) Заполняет элементы указанного массива байтов случайными числами. Next Double() Возвращает случайное число с плавающей запятой, которое больше или равно 0,0 и меньше 1,0. NextSingle() Возвращает случайное число с плавающей запятой в диапазоне от 0,0 до 1,0. Пример использования класса Random в приложениях C#
byte[] bytes = new byte[100];//создаем массив на 100 элементов Random rnd = new Random(); //создаем объект класса rnd1.NextBytes(bytes);//генерация 100 случайных байтов
или, если необходимо получить одно случайное число, то можно воспользоваться методами Next :
int a = rnd1.Next(); //случайное целое число int b = rnd1.Next(100);//случайное целое число меньше 100 int c = rnd1.Next(-100, 100); //случайное число от -100 до 100 Console.WriteLine(a); Console.WriteLine(b); Console.WriteLine(c);
1130675615
53
-5Если вы планируете использовать объекты класса Random в потоках, то необходимо использовать потокобезопасный экземпляр, используя свойство Shared класса, например, так:
Random threadSafeRnd = Random.Shared;
Проблемы с Random
По данным разработчиков, в большинстве систем Windows объекты Random , созданные с интервалом в 15 миллисекунд друг от друга, скорее всего, будут иметь одинаковые начальные значения. Возможно, что это утверждение относится только к .NET Framework (или же информация на сайте Microsoft устарела), так как для .NET 7 пример этой проблемы, предоставленный самой Microsoft, у меня показывал абсолютно различные ряды случайных чисел, несмотря на соблюдение всех условий — создание двух экземпляров Random в течение 15 мс и менее, ряд на 100 элементов и т.д.
Класс RandomNumberGenerator
Этот класс расположен в пространстве имен System.Security.Cryptography и предназначен для создания криптографически надежных случайных значений. Класс абстрактный, поэтому создавать напрямую мы его не можем, но можем использовать классы, его реализующие, например, классом RNGCrypto Service Provider , который на данный момент не рекомендуется использовать или же, как рекомендуют разработчики из Microsoft — использовать статические методы класса. Посмотрим как работает RandomNumberGenerator .
Статические методы RandomNumberGenerator
Если не создавать наследника для RandomNumberGenerator , то для генерации случайных чисел мы можем воспользоваться следующими статическими методами класса:
Метод Описание Create() Создает экземпляр реализации по умолчанию криптографического генератора случайных чисел, позволяющего генерировать случайные данные. Fill(Span) Заполняет диапазон криптостойкими случайными байтами. Get Bytes(Int32) Создает массив байтов с криптографически строгой случайной последовательностью значений. Get Int32(Int32) Создает случайное целое число от 0 (включительно) до указанного исключенного верхнего предела, используя генератор криптостойких случайных чисел. Get Int32(Int32, Int32) Создает случайное целое число от указанного нижнего предела (включенного ) до указанного верхнего предела (исключая его), используя генератор криптостойких случайных чисел. Примеры использования этих методов представлены ниже:
Span bytes = new Span(bytes1); RandomNumberGenerator.Fill(bytes); bytes2 = RandomNumberGenerator.GetBytes(bytes2.Length); int a = RandomNumberGenerator.GetInt32(100); //случайное число до 100 int b = RandomNumberGenerator.GetInt32(-100, 100); //случайное число от -100 до 100
Проблемы с RandomNumberGenerator
RandomNumberGenerator использует более сложные алгоритмы для генерации случайных чисел и их последовательностей, а за качество нам приходится «платить» скоростью. Поэтому при прочих равных условиях RandomNumberGenerator будет работать всегда медленнее, чем Random . Ниже в таблице, для примера, показано время в миллисекундах которое потребовалось двум генераторам для генерации 1000 000 случайных величин
# цикла Random RandomNumberGenerator 1 9 187 2 10 184 3 9 182 Итого
Для генерации случайных чисел в C# могут использоваться два класса — Random и RandomNumberGenerator . При этом, класс Random обладает большей производительностью, однако, является менее надежным, чем RandomNumberGenerator , который использует более сложные алгоритмы генерации случайных величин и используется в работе алгоритмов шифрования.
уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.
Random. Next Метод
Некоторые сведения относятся к предварительной версии продукта, в которую до выпуска могут быть внесены существенные изменения. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.
Возвращает случайное целое число.
Перегрузки
Возвращает неотрицательное случайное целое число.
Возвращает неотрицательное случайное целое число, которое меньше указанного максимального значения.
Возвращает случайное целое число в указанном диапазоне.
Next()
Возвращает неотрицательное случайное целое число.
public: virtual int Next();public virtual int Next ();abstract member Next : unit -> int override this.Next : unit -> intPublic Overridable Function Next () As IntegerВозвращаемое значение
32-разрядное целое число со знаком, которое больше или равно 0 и меньше Int32.MaxValue.
Примеры
В следующем примере выполняются повторные Next вызовы метода для создания определенного числа случайных чисел, запрошенных пользователем. Метод Console.ReadLine используется для получения данных, введенных клиентом.
using namespace System; void main() < Console::Write("Number of random numbers to generate: "); String^ line = Console::ReadLine(); unsigned int numbers = 0; Random^ rnd = gcnew Random(); if (! UInt32::TryParse(line, numbers)) numbers = 10; for (unsigned int ctr = 1; ctr ", rnd->Next()); > // The example displays output like the following when asked to generate // 15 random numbers: // Number of random numbers to generate: 15 // 1,733,189,596 // 566,518,090 // 1,166,108,546 // 1,931,426,514 // 1,341,108,291 // 1,012,698,049 // 890,578,409 // 1,377,589,722 // 2,108,384,181 // 1,532,939,448 // 762,207,767 // 815,074,920 // 1,521,208,785 // 1,950,436,671 // 1,266,596,666Random rnd = new Random(); Console.WriteLine("Generating 10 random numbers:"); for (uint ctr = 1; ctr "); // The example displays output like the following: // // Generating 10 random numbers: // 1,733,189,596 // 566,518,090 // 1,166,108,546 // 1,931,426,514 // 1,532,939,448 // 762,207,767 // 815,074,920 // 1,521,208,785 // 1,950,436,671 // 1,266,596,666let rnd = Random() printfn "Generating 10 random numbers:" for _ = 1 to 10 do printfn $"" // The example displays output like the following: // // Generating 10 random numbers: // 1,733,189,596 // 566,518,090 // 1,166,108,546 // 1,931,426,514 // 1,532,939,448 // 762,207,767 // 815,074,920 // 1,521,208,785 // 1,950,436,671 // 1,266,596,666Module Example Public Sub Main() Console.Write("Number of random numbers to generate: ") Dim line As String = Console.ReadLine() Dim numbers As UInteger = 0 Dim rnd As New Random() If Not UInt32.TryParse(line, numbers) Then numbers = 10 For ctr As UInteger = 1 To numbers Console.WriteLine("", rnd.Next()) Next End Sub End Module ' The example displays output like the following when asked to generate ' 15 random numbers: ' Number of random numbers to generate: 15 ' 1,733,189,596 ' 566,518,090 ' 1,166,108,546 ' 1,931,426,514 ' 1,341,108,291 ' 1,012,698,049 ' 890,578,409 ' 1,377,589,722 ' 2,108,384,181 ' 1,532,939,448 ' 762,207,767 ' 815,074,920 ' 1,521,208,785 ' 1,950,436,671 ' 1,266,596,666В следующем примере класс является производным от Random для создания последовательности случайных чисел, распределение которых отличается от равномерного распределения, созданного Sample методом базового класса. Он переопределяет Sample метод , чтобы обеспечить распределение случайных чисел, и переопределяет Random.Next метод для использования ряда случайных чисел.
using namespace System; // This derived class converts the uniformly distributed random // numbers generated by base.Sample() to another distribution. public ref class RandomProportional : Random < // The Sample method generates a distribution proportional to the value // of the random numbers, in the range [0.0, 1.0]. protected: virtual double Sample() override < return Math::Sqrt(Random::Sample()); >public: RandomProportional() <> virtual int Next() override < return (int) (Sample() * Int32::MaxValue); >>; int main(array ^args) < const int rows = 4, cols = 6; const int runCount = 1000000; const int distGroupCount = 10; const double intGroupSize = ((double) Int32::MaxValue + 1.0) / (double)distGroupCount; RandomProportional ^randObj = gcnew RandomProportional(); array^ intCounts = gcnew array(distGroupCount); array^ realCounts = gcnew array(distGroupCount); Console::WriteLine( "\nThe derived RandomProportional class overrides " + "the Sample method to \ngenerate random numbers " + "in the range [0.0, 1.0]. The distribution \nof " + "the numbers is proportional to their numeric values. " + "For example, \nnumbers are generated in the " + "vicinity of 0.75 with three times the \n" + "probability of those generated near 0.25."); Console::WriteLine( "\nRandom doubles generated with the NextDouble() " + "method:\n"); // Generate and display [rows * cols] random doubles. for (int i = 0; i < rows; i++) < for (int j = 0; j < cols; j++) Console::Write("", randObj->NextDouble()); Console::WriteLine(); > Console::WriteLine( "\nRandom integers generated with the Next() " + "method:\n"); // Generate and display [rows * cols] random integers. for (int i = 0; i < rows; i++) < for (int j = 0; j < cols; j++) Console::Write("", randObj->Next()); Console::WriteLine(); > Console::WriteLine( "\nTo demonstrate the proportional distribution, " + " random \nintegers and doubles are grouped " + "into equal value ranges. This \n" + "is the count of values in each range:\n", runCount, distGroupCount); Console::WriteLine( "", "Integer Range", "Count", "Double Range", "Count"); Console::WriteLine( "", "-------------", "-----", "------------", "-----"); // Generate random integers and doubles, and then count // them by group. for (int i = 0; i < runCount; i++) < intCounts[ (int)((double)randObj->Next() / intGroupSize) ]++; realCounts[ (int)(randObj->NextDouble() * (double)distGroupCount) ]++; > // Display the count of each group. for (int i = 0; i < distGroupCount; i++) Console::WriteLine( "--", (int)((double)i * intGroupSize), (int)((double)(i + 1) * intGroupSize - 1.0), intCounts[ i ], ((double)i) / (double)distGroupCount, ((double)(i + 1)) / (double)distGroupCount, realCounts[ i ]); return 0; > /* This example of Random.Sample() displays output similar to the following: The derived RandomProportional class overrides the Sample method to generate random numbers in the range [0.0, 1.0). The distribution of the numbers is proportional to the number values. For example, numbers are generated in the vicinity of 0.75 with three times the probability of those generated near 0.25. Random doubles generated with the NextDouble() method: 0.59455719 0.17589882 0.83134398 0.35795862 0.91467727 0.54022658 0.93716947 0.54817519 0.94685080 0.93705478 0.18582318 0.71272428 0.77708682 0.95386216 0.70412393 0.86099417 0.08275804 0.79108316 0.71019941 0.84205103 0.41685082 0.58186880 0.89492302 0.73067715 Random integers generated with the Next() method: 1570755704 1279192549 1747627711 1705700211 1372759203 1849655615 2046235980 1210843924 1554274149 1307936697 1480207570 1057595022 337854215 844109928 2028310798 1386669369 2073517658 1291729809 1537248240 1454198019 1934863511 1640004334 2032620207 534654791 To demonstrate the proportional distribution, 1,000,000 random integers and doubles are grouped into 10 equal value ranges. This is the count of values in each range: Integer Range Count Double Range Count ------------- ----- ------------ ----- 0- 214748363 10,079 0.00000-0.10000 10,148 214748364- 429496728 29,835 0.10000-0.20000 29,849 429496729- 644245093 49,753 0.20000-0.30000 49,948 644245094- 858993458 70,325 0.30000-0.40000 69,656 858993459-1073741823 89,906 0.40000-0.50000 90,337 1073741824-1288490187 109,868 0.50000-0.60000 110,225 1288490188-1503238552 130,388 0.60000-0.70000 129,986 1503238553-1717986917 149,231 0.70000-0.80000 150,428 1717986918-1932735282 170,234 0.80000-0.90000 169,610 1932735283-2147483647 190,381 0.90000-1.00000 189,813 */using System; // This derived class converts the uniformly distributed random // numbers generated by base.Sample() to another distribution. public class RandomProportional : Random < // The Sample method generates a distribution proportional to the value // of the random numbers, in the range [0.0, 1.0]. protected override double Sample() < return Math.Sqrt(base.Sample()); >public override int Next() < return (int) (Sample() * int.MaxValue); >> public class RandomSampleDemo < static void Main() < const int rows = 4, cols = 6; const int runCount = 1000000; const int distGroupCount = 10; const double intGroupSize = ((double)int.MaxValue + 1.0) / (double)distGroupCount; RandomProportional randObj = new RandomProportional(); int[ ] intCounts = new int[ distGroupCount ]; int[ ] realCounts = new int[ distGroupCount ]; Console.WriteLine( "\nThe derived RandomProportional class overrides " + "the Sample method to \ngenerate random numbers " + "in the range [0.0, 1.0]. The distribution \nof " + "the numbers is proportional to their numeric values. " + "For example, \nnumbers are generated in the " + "vicinity of 0.75 with three times the \n" + "probability of those generated near 0.25."); Console.WriteLine( "\nRandom doubles generated with the NextDouble() " + "method:\n"); // Generate and display [rows * cols] random doubles. for (int i = 0; i < rows; i++) < for (int j = 0; j < cols; j++) Console.Write("", randObj.NextDouble()); Console.WriteLine(); > Console.WriteLine( "\nRandom integers generated with the Next() " + "method:\n"); // Generate and display [rows * cols] random integers. for (int i = 0; i < rows; i++) < for (int j = 0; j < cols; j++) Console.Write("", randObj.Next()); Console.WriteLine(); > Console.WriteLine( "\nTo demonstrate the proportional distribution, " + " random \nintegers and doubles are grouped " + "into equal value ranges. This \n" + "is the count of values in each range:\n", runCount, distGroupCount); Console.WriteLine( "", "Integer Range", "Count", "Double Range", "Count"); Console.WriteLine( "", "-------------", "-----", "------------", "-----"); // Generate random integers and doubles, and then count // them by group. for (int i = 0; i < runCount; i++) < intCounts[ (int)((double)randObj.Next() / intGroupSize) ]++; realCounts[ (int)(randObj.NextDouble() * (double)distGroupCount) ]++; >// Display the count of each group. for (int i = 0; i < distGroupCount; i++) Console.WriteLine( "--", (int)((double)i * intGroupSize), (int)((double)(i + 1) * intGroupSize - 1.0), intCounts[ i ], ((double)i) / (double)distGroupCount, ((double)(i + 1)) / (double)distGroupCount, realCounts[ i ]); > > /* This example of Random.Sample() displays output similar to the following: The derived RandomProportional class overrides the Sample method to generate random numbers in the range [0.0, 1.0). The distribution of the numbers is proportional to the number values. For example, numbers are generated in the vicinity of 0.75 with three times the probability of those generated near 0.25. Random doubles generated with the NextDouble() method: 0.59455719 0.17589882 0.83134398 0.35795862 0.91467727 0.54022658 0.93716947 0.54817519 0.94685080 0.93705478 0.18582318 0.71272428 0.77708682 0.95386216 0.70412393 0.86099417 0.08275804 0.79108316 0.71019941 0.84205103 0.41685082 0.58186880 0.89492302 0.73067715 Random integers generated with the Next() method: 1570755704 1279192549 1747627711 1705700211 1372759203 1849655615 2046235980 1210843924 1554274149 1307936697 1480207570 1057595022 337854215 844109928 2028310798 1386669369 2073517658 1291729809 1537248240 1454198019 1934863511 1640004334 2032620207 534654791 To demonstrate the proportional distribution, 1,000,000 random integers and doubles are grouped into 10 equal value ranges. This is the count of values in each range: Integer Range Count Double Range Count ------------- ----- ------------ ----- 0- 214748363 10,079 0.00000-0.10000 10,148 214748364- 429496728 29,835 0.10000-0.20000 29,849 429496729- 644245093 49,753 0.20000-0.30000 49,948 644245094- 858993458 70,325 0.30000-0.40000 69,656 858993459-1073741823 89,906 0.40000-0.50000 90,337 1073741824-1288490187 109,868 0.50000-0.60000 110,225 1288490188-1503238552 130,388 0.60000-0.70000 129,986 1503238553-1717986917 149,231 0.70000-0.80000 150,428 1717986918-1932735282 170,234 0.80000-0.90000 169,610 1932735283-2147483647 190,381 0.90000-1.00000 189,813 */' This derived class converts the uniformly distributed random ' numbers generated by base.Sample() to another distribution. Public Class RandomProportional Inherits Random ' The Sample method generates a distribution proportional to the value ' of the random numbers, in the range [0.0, 1.0]. Protected Overrides Function Sample() As Double Return Math.Sqrt(MyBase.Sample()) End Function Public Overrides Function [Next]() As Integer Return Sample() * Integer.MaxValue End Function End Class Module RandomSampleDemo Sub Main() Const rows As Integer = 4, cols As Integer = 6 Const runCount As Integer = 1000000 Const distGroupCount As Integer = 10 Const intGroupSize As Double = _ (CDbl(Integer.MaxValue) + 1.0) / _ CDbl(distGroupCount) Dim randObj As New RandomProportional() Dim intCounts(distGroupCount) As Integer Dim realCounts(distGroupCount) As Integer Dim i As Integer, j As Integer Console.WriteLine(vbCrLf & _ "The derived RandomProportional class overrides " & _ "the Sample method to " & vbCrLf & _ "generate random numbers in the range " & _ "[0.0, 1.0]. The distribution " & vbCrLf & _ "of the numbers is proportional to their numeric " & _ "values. For example, " & vbCrLf & _ "numbers are generated in the vicinity of 0.75 " & _ "with three times " & vbCrLf & "the " & _ "probability of those generated near 0.25.") Console.WriteLine(vbCrLf & _ "Random doubles generated with the NextDouble() " & _ "method:" & vbCrLf) ' Generate and display [rows * cols] random doubles. For i = 0 To rows - 1 For j = 0 To cols - 1 Console.Write("", randObj.NextDouble()) Next j Console.WriteLine() Next i Console.WriteLine(vbCrLf & _ "Random integers generated with the Next() " & _ "method:" & vbCrLf) ' Generate and display [rows * cols] random integers. For i = 0 To rows - 1 For j = 0 To cols - 1 Console.Write("", randObj.Next()) Next j Console.WriteLine() Next i Console.WriteLine(vbCrLf & _ "To demonstrate the proportional distribution, " & _ " random " & vbCrLf & _ "integers and doubles are grouped into " & _ "equal value ranges. This " & vbCrLf & _ "is the count of values in each range:" & vbCrLf, _ runCount, distGroupCount) Console.WriteLine("", _ "Integer Range", "Count", "Double Range", "Count") Console.WriteLine("", _ "-------------", "-----", "------------", "-----") ' Generate random integers and doubles, and then count ' them by group. For i = 0 To runCount - 1 intCounts(Fix(CDbl(randObj.Next()) / _ intGroupSize)) += 1 realCounts(Fix(randObj.NextDouble() * _ CDbl(distGroupCount))) += 1 Next i ' Display the count of each group. For i = 0 To distGroupCount - 1 Console.WriteLine( _ "--", _ Fix(CDbl(i) * intGroupSize), _ Fix(CDbl(i + 1) * intGroupSize - 1.0), _ intCounts(i), _ CDbl(i) / CDbl(distGroupCount), _ CDbl(i + 1) / CDbl(distGroupCount), _ realCounts(i)) Next i End Sub End Module ' This example of Random.Sample() generates output similar to the following: ' ' The derived RandomProportional class overrides the Sample method to ' generate random numbers in the range [0.0, 1.0]. The distribution ' of the numbers is proportional to their numeric values. For example, ' numbers are generated in the vicinity of 0.75 with three times ' the probability of those generated near 0.25. ' ' Random doubles generated with the NextDouble() method: ' ' 0.28377004 0.75920598 0.33430371 0.66720626 0.97080243 0.27353772 ' 0.17787962 0.54618410 0.08145080 0.56286100 0.99002910 0.64898614 ' 0.27673277 0.99455281 0.93778966 0.76162002 0.70533771 0.44375798 ' 0.55939883 0.87383136 0.66465779 0.77392566 0.42393411 0.82409159 ' ' Random integers generated with the Next() method: ' ' 1364479914 1230312341 1657373812 1526222928 988564704 700078020 ' 1801013705 1541517421 1146312560 338318389 1558995993 2027260859 ' 884520932 1320070465 570200106 1027684711 943035246 2088689333 ' 630809089 1705728475 2140787648 2097858166 1863010875 1386804198 ' ' To demonstrate the proportional distribution, 1,000,000 random ' integers and doubles are grouped into 10 equal value ranges. This ' is the count of values in each range: ' ' Integer Range Count Double Range Count ' ------------- ----- ------------ ----- ' 0- 214748363 9,892 0.00000-0.10000 9,928 ' 214748364- 429496728 30,341 0.10000-0.20000 30,101 ' 429496729- 644245093 49,958 0.20000-0.30000 49,964 ' 644245094- 858993458 70,099 0.30000-0.40000 70,213 ' 858993459-1073741823 90,801 0.40000-0.50000 89,553 ' 1073741824-1288490187 109,699 0.50000-0.60000 109,427 ' 1288490188-1503238552 129,438 0.60000-0.70000 130,339 ' 1503238553-1717986917 149,886 0.70000-0.80000 150,000 ' 1717986918-1932735282 170,338 0.80000-0.90000 170,128 ' 1932735283-2147483647 189,548 0.90000-1.00000 190,347Комментарии
Random.Next создает случайное число, значение которого в диапазоне от 0 до меньше Int32.MaxValue. Чтобы создать случайное число, значение которого колеблется от 0 до другого положительного числа, используйте перегрузку Random.Next(Int32) метода . Чтобы создать случайное число в другом диапазоне, используйте перегрузку Random.Next(Int32, Int32) метода .
Примечания для тех, кто наследует этот метод
Начиная с платформа .NET Framework версии 2.0, если вы наследуете класс от Random метода и переопределите Sample() его, распределение, предоставляемое реализацией производного Sample() класса метода, не используется в вызовах Next() реализации базового класса метода. Вместо этого используется равномерное распределение, возвращаемое базовым Random классом. Это поведение повышает общую производительность Random класса . Чтобы изменить это поведение для вызова Sample() метода в производном классе, необходимо также переопределить Next() метод .
- Базовый курс C#
