Как мне сгенерировать случайное число int?
- 1
- 2
Класс Random
используется для создания случайных чисел. (Псевдослучайный, конечно.)
Пример:
Random rnd = new Random();
int month = rnd.Next(1, 13); // creates a number between 1 and 12
int dice = rnd.Next(1, 7); // creates a number between 1 and 6
int card = rnd.Next(52); // creates a number between 0 and 51
Если вы собираетесь создать более одного случайного числа, вам следует сохранить экземпляр Random
и использовать его повторно. Если вы создаете новые экземпляры слишком близко по времени, они будут производить ту же серию случайных чисел, что и генератор случайных чисел, высеянный из системных часов.
Вопрос выглядит очень простым, но ответ немного сложен. Если вы видите, почти все предложили использовать класс Random, а некоторые предложили использовать крипто-класс RNG. Но тогда когда выбирать что.
Для этого нам нужно сначала понять термин СЛУЧАЙНОСТЬ и его философию.
Я бы посоветовал вам посмотреть это видео, которое углубляется в философию случайности с использованием С# https://www.youtube.com/watch?v=tCYxc-2-3fY
Прежде всего, давайте поймем философию СЛУЧАЙНОСТИ. Когда мы говорим человеку выбирать между КРАСНЫМ, ЗЕЛЕНЫМ и ЖЕЛТЫМ, что происходит внутри. Что заставляет человека выбирать КРАСНЫЙ, ЖЕЛТЫЙ или ЗЕЛЕНЫЙ?
Некоторая начальная мысль приходит в ум человека, который решает его выбор, это может быть любимый цвет, счастливый цвет и так далее. Другими словами, некоторый начальный триггер, который мы называем в СЛУЧАЙНОМ как SEED. Этот SEED является начальной точкой, триггером, побуждающим его выбрать СЛУЧАЙНОЕ значение.
Теперь, если SEED легко угадать, то такие виды случайных чисел называются PSEUDO, а когда семя трудно угадать, эти случайные числа называются ЗАЩИЩЕННЫМИ случайными числами.
Например, человек выбирает цвет в зависимости от сочетания погоды и звука, тогда будет сложно угадать начальное зерно.
Теперь позвольте мне сделать важное выражение: -
* Класс 'Случайный' генерирует только случайное число PSEUDO, и для генерации БЕЗОПАСНОГО случайного числа нам нужно использовать класс 'RNGCryptoServiceProvider'.
Случайный класс берет начальные значения из вашего процессора, что очень предсказуемо. Другими словами, СЛУЧАЙНЫЙ класс С# генерирует псевдослучайные числа, ниже приведен код того же самого.
** Примечание: ** .NET Core 2.0.0+
использует другое начальное число в конструкторе без параметров: вместо тактовой частоты процессора он использует Guid.NewGuid().GetHashCode()
.
var random = new Random();
int randomnumber = random.Next()
В то время как класс RNGCryptoServiceProvider
использует энтропию ОС для генерации семян. Энтропия ОС - это случайное значение, которое генерируется с использованием звука, щелчков мыши и таймингов клавиатуры, температуры и т.д. Ниже приведен код для того же.
using (RNGCryptoServiceProvider rg = new RNGCryptoServiceProvider())
{
byte[] rno = new byte[5];
rg.GetBytes(rno);
int randomvalue = BitConverter.ToInt32(rno, 0);
}
Чтобы понять энтропию ОС, посмотрите это видео с 14:30 https://www.youtube.com/watch?v=tCYxc-2-3fY, где объясняется логика энтропии ОС. Таким образом, говоря простыми словами, RNG Crypto генерирует БЕЗОПАСНЫЕ случайные числа.
Каждый раз, когда вы делаете новый Random(), он инициализируется. Это означает, что в тесном цикле вы получаете одно и то же значение много раз. Вы должны сохранить один экземпляр Random и продолжать использовать Next на том же экземпляре.
//Function to get random number
private static readonly Random getrandom = new Random();
public static int GetRandomNumber(int min, int max)
{
lock(getrandom) // synchronize
{
return getrandom.Next(min, max);
}
}
Остерегайтесь того, что new Random()
добавляется в текущую метку времени.
Если вы хотите сгенерировать только один номер, вы можете использовать:
new Random().Next( int.MinValue, int.MaxValue )
Для получения дополнительной информации посмотрите на класс Random, хотя, пожалуйста, обратите внимание:
Однако, поскольку часы имеют конечное разрешение, использование конструктора без параметров для создания различных случайных объектов в тесной последовательности создает генераторы случайных чисел, которые создают идентичные последовательности случайных чисел.
Поэтому не используйте этот код для генерации серии случайных чисел.
Я хотел добавить криптографически безопасную версию:
Класс RNGCryptoServiceProvider (MSDN или dotnetperls)
Он реализует IDisposable.
using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider())
{
byte[] randomNumber = new byte[4];//4 for int32
rng.GetBytes(randomNumber);
int value = BitConverter.ToInt32(randomNumber, 0);
}
Вы можете использовать метод Jon Skeet StaticRandom внутри библиотеки классов MiscUtil, которую он построил для псевдослучайного числа.
using MiscUtil;
...
for (int i = 0; i < 100;
Console.WriteLine(StaticRandom.Next());
лучше заполнить объект Random текущими миллисекундами, чтобы обеспечить истинное случайное число, и вы почти не найдете дубликаты, использующие его много раз
Random rand = new Random(DateTime.Now.Millisecond);
Обновить
Я знаю, что new Random()
использует текущие тики в качестве начального числа, но задание с текущими миллисекундами все еще достаточно хорошо, так как это хороший случайный запуск
Последний оставшийся момент заключается в том, что вам не нужно инициализировать new Random()
каждый раз, когда вам нужно случайное число, инициировать один объект Random, затем использовать его столько раз, сколько вам нужно внутри цикла или что-то еще
Я пробовал все эти решения, исключая ответ COBOL... lol
Ни одно из этих решений не было достаточно хорошим. Мне нужны рандомы в быстром для цикла int, и я получал тонны повторяющихся значений даже в очень широких пределах. После долгого урегулирования случайных результатов я решил окончательно решить эту проблему раз и навсегда.
Все о семени.
Я создаю случайное целое, анализируя нецифровые данные от Guid, затем я использую это, чтобы создать экземпляр класса Random.
public int GenerateRandom(int min, int max)
{
var seed = Convert.ToInt32(Regex.Match(Guid.NewGuid().ToString(), @"\d+").Value);
return new Random(seed).Next(min, max);
}
Обновление: седирование не требуется, если вы создаете экземпляр класса Random один раз. Поэтому было бы лучше создать статический класс и вызвать метод с этим.
public static class IntUtil
{
private static Random random;
private static void Init()
{
if (random == null) random = new Random();
}
public static int Random(int min, int max)
{
Init();
return random.Next(min, max);
}
}
Затем вы можете использовать статический класс, как это сделать.
for(var i = 0; i < 1000; i++)
{
int randomNumber = IntUtil.Random(1,100);
Console.WriteLine(randomNumber);
}
Я признаю, что мне нравится этот подход лучше.
Модифицированный ответ отсюда.
Если у вас есть доступ к процессору, совместимому с Intel Secure Key, вы можете генерировать реальные случайные числа и строки, используя следующие библиотеки: https://github.com/JebteK/RdRand и https://www.rdrand.com/
Просто скачайте последнюю версию отсюда, включите Jebtek.RdRand и добавьте для него оператор использования. Затем все, что вам нужно сделать, это:
// Check to see if this is a compatible CPU
bool isAvailable = RdRandom.GeneratorAvailable();
// Generate 10 random characters
string key = RdRandom.GenerateKey(10);
// Generate 64 random characters, useful for API keys
string apiKey = RdRandom.GenerateAPIKey();
// Generate an array of 10 random bytes
byte[] b = RdRandom.GenerateBytes(10);
// Generate a random unsigned int
uint i = RdRandom.GenerateUnsignedInt();
Если у вас нет совместимого процессора для выполнения кода, просто используйте службы RESTful на rdrand.com. С библиотекой оболочки RdRandom, включенной в ваш проект, вам просто нужно сделать это (вы получаете 1000 бесплатных звонков при регистрации):
string ret = Randomizer.GenerateKey(<length>, "<key>");
uint ret = Randomizer.GenerateUInt("<key>");
byte[] ret = Randomizer.GenerateBytes(<length>, "<key>");
Цифры, генерируемые встроенным классом Random
(System.Random), генерируют псевдослучайные числа.
Если вам нужны истинные случайные числа, самое близкое, что мы можем получить, это "безопасный псевдослучайный генератор", который может быть сгенерирован с использованием криптографических классов в С#, таких как RNGCryptoServiceProvider
.
Тем не менее, если вам все еще нужны истинные случайные числа, вам нужно будет использовать внешний источник, такой как устройства, учитывающие радиоактивный распад, в качестве семени для генератора случайных чисел. Поскольку, по определению, любое число, порожденное чисто алгоритмическими средствами, не может быть по-настоящему случайным.
Я использую ниже код для случайного числа:
var random = new Random((int)DateTime.Now.Ticks);
var randomValue = random.Next(startValue, endValue + 1);
Это класс, который я использую. Работает как RandomNumber.GenerateRandom(1, 666)
internal static class RandomNumber
{
private static Random r = new Random();
private static object l = new object();
private static Random globalRandom = new Random();
[ThreadStatic]
private static Random localRandom;
public static int GenerateNewRandom(int min, int max)
{
return new Random().Next(min, max);
}
public static int GenerateLockedRandom(int min, int max)
{
int result;
lock (RandomNumber.l)
{
result = RandomNumber.r.Next(min, max);
}
return result;
}
public static int GenerateRandom(int min, int max)
{
Random random = RandomNumber.localRandom;
if (random == null)
{
int seed;
lock (RandomNumber.globalRandom)
{
seed = RandomNumber.globalRandom.Next();
}
random = (RandomNumber.localRandom = new Random(seed));
}
return random.Next(min, max);
}
}
Пока все в порядке:
Random random = new Random();
int randomNumber = random.Next()
Вы хотите контролировать ограничение (min и max mumbers) большую часть времени. Поэтому вам нужно указать, где начинается и заканчивается случайное число.
Метод Next()
принимает два параметра: min и max.
Итак, если я хочу, чтобы мое случайное число было между 5 и 15, я просто делал
int randomNumber = random.Next(5, 16)
Random random = new Random ();
int randomNumber = random.Next (lowerBound,upperBound);
Для сильных случайных семян я всегда использую CryptoRNG, а не Time.
using System;
using System.Security.Cryptography;
public class Program
{
public static void Main()
{
var random = new Random(GetSeed());
Console.WriteLine(random.Next());
}
public static int GetSeed()
{
using (var rng = new RNGCryptoServiceProvider())
{
var intBytes = new byte[4];
rng.GetBytes(intBytes);
return BitConverter.ToInt32(intBytes, 0);
}
}
}
Random rand = new Random();
int name = rand.Next()
Поместите любые значения, которые вы хотите во второй круглый скоб убедитесь, что вы установили имя, написав подсказку и двойную вкладку, чтобы сгенерировать код
Числа, вычисленные компьютером через детерминированный процесс, по определению не могут быть случайными.
Если вам нужны настоящие случайные числа, случайность возникает из-за атмосферного шума или радиоактивного распада.
Вы можете попробовать, например, RANDOM.ORG(это снижает производительность)
Я хотел продемонстрировать, что происходит, когда новый случайный генератор используется каждый раз. Предположим, у вас есть два метода или два класса, для каждого из которых требуется случайное число. И наивно вы их кодируете, как:
public class A
{
public A()
{
var rnd=new Random();
ID=rnd.Next();
}
public int ID { get; private set; }
}
public class B
{
public B()
{
var rnd=new Random();
ID=rnd.Next();
}
public int ID { get; private set; }
}
Как вы думаете, вы получите два разных идентификатора? NOPE
class Program
{
static void Main(string[] args)
{
A a=new A();
B b=new B();
int ida=a.ID, idb=b.ID;
// ida = 1452879101
// idb = 1452879101
}
}
Решение состоит в том, чтобы всегда использовать один статический случайный генератор. Вот так:
public static class Utils
{
public static readonly Random random=new Random();
}
public class A
{
public A()
{
ID=Utils.random.Next();
}
public int ID { get; private set; }
}
public class B
{
public B()
{
ID=Utils.random.Next();
}
public int ID { get; private set; }
}
Следующий код возвращает случайное число.
int num = random.Next();
Следующий код возвращает случайное число меньше 1000.
int num = random.Next(1000);
Следующий код возвращает случайное число между минимальным и максимальным диапазоном.
Генерирует случайное число между двумя числами:
public int RandomNumber(int min, int max)
{
Random random = new Random();
return random.Next(min, max);
}
Вы можете попробовать со случайным начальным значением, используя ниже:
var rnd = new Random(11111111); //note: seed value is 11111111
string randomDigits = rnd.Next();
var requestNumber = $"SD-{randomDigits}";
Я предполагаю, что вы хотите равномерно распределенный генератор случайных чисел, как показано ниже. Случайные числа в большинстве языков программирования, включая С# и C++, не перетасовываются должным образом перед их использованием. Это означает, что вы будете получать одно и то же число снова и снова, что на самом деле не случайно. Чтобы не рисовать одно и то же число снова и снова, вам нужно семя. Как правило, тики во времени хорошо для этой задачи. Помните, что вы будете получать одно и то же число снова и снова, если будете использовать одно и то же семя каждый раз. Поэтому старайтесь всегда использовать разные семена. Время является хорошим источником для семян, потому что они всегда растеряны.
int GetRandomNumber(int min, int max)
{
Random rand = new Random((int)DateTime.Now.Ticks);
return rand.Next(min, max);
}
если вы ищете генератор случайных чисел для нормального распределения, вы можете использовать преобразование Бокса-Мюллера. Проверьте ответ по yoyoyoyosef в вопросе о случайной гауссовой переменной. Поскольку вам нужно целое число, вы должны привести в конце двойное значение к целому.
Random rand = new Random(); //reuse this if you are generating many
double u1 = 1.0-rand.NextDouble(); //uniform(0,1] random doubles
double u2 = 1.0-rand.NextDouble();
double randStdNormal = Math.Sqrt(-2.0 * Math.Log(u1)) *
Math.Sin(2.0 * Math.PI * u2); //random normal(0,1)
double randNormal =
mean + stdDev * randStdNormal; //random normal(mean,stdDev^2)
К сожалению, OP действительно требует случайного значения int
, но для простой цели обмена знаниями, если вы хотите случайное значение BigInteger
вы можете использовать следующее утверждение:
BigInteger randomVal = BigInteger.Abs(BigInteger.Parse(Guid.NewGuid().ToString().Replace("-",""), NumberStyles.AllowHexSpecifier));
Самый простой способ, вероятно, это просто Random.range(1, 3)
Это сгенерирует число от 1 до 2.
Просто как примечание для дальнейшего использования.
Если вы используете .NET Core, несколько экземпляров Random не так опасны, как раньше. Я знаю, что этот вопрос относится к 2010 году, но, поскольку этот вопрос старый, но имеет некоторую привлекательность, я думаю, что это хорошо - документировать изменения.
Вы можете обратиться к этому вопросу, который я задал пару недель назад:
Microsoft изменила случайное начальное число по умолчанию?
По сути, они изменили начальное значение по умолчанию с Environment.TickCount
на Guid.NewGuid().GetHashCode()
, поэтому, если вы создадите 2 экземпляра Random, он не будет отображать одинаковые числа.
Вы можете увидеть различия в файлах из .NET Framework/.NET Core (2.0. 0+) здесь: https://github.com/dotnet/coreclr/pull/2192/commits/9f6a0b675e5ac0065a268554de49162c539ff66d
Он не так безопасен, как RNGCryptoServiceProvider, но по крайней мере он не даст вам странных результатов.
Попробуйте эти простые шаги для создания случайных чисел:
Создать функцию:
private int randomnumber(int min, int max)
{
Random rnum = new Random();
return rnum.Next(min, max);
}
Используйте вышеуказанную функцию в месте, где вы хотите использовать случайные числа. Предположим, вы хотите использовать его в текстовом поле.
textBox1.Text = randomnumber(0, 999).ToString();
0 - это минимум, а 999 - это максимум. Вы можете изменить значения на то, что вы хотите.
Почему бы не использовать int randomNumber = Random.Range(start_range, end_range)
?
Я надеюсь, что этот код может быть полезен
public static string GeneratePassword()
{
string strPwdchar = "abcdefghijklmnopqrstuvwxyz0123456789#[email protected]&$ABCDEFGHIJKLMNOPQRSTUVWXYZ";
string strPwd = "";
Random rnd = new Random();
for (int i = 0; i <= 7; i++)
{
int iRandom = rnd.Next(5, strPwdchar.Length - 1);
strPwd += strPwdchar.Substring(iRandom, 1);
}
return strPwd;
}
Играйте с ним... надеюсь, вы сможете получить то, что хотите.
Быстро и легко для встраивания, используйте ниже код:
new Random().Next(min, max);
// for example unique name
strName += "_" + new Random().Next(100, 999);
У меня всегда есть методы, которые генерируют случайные числа, которые помогают для различных целей. Я надеюсь, что это может помочь вам тоже:
public class RandomGenerator
{
public int RandomNumber(int min, int max)
{
var random = new Random();
return random.Next(min, max);
}
public string RandomString(int size, bool lowerCase)
{
var builder = new StringBuilder();
var random = new Random();
char ch;
for (int i = 0; i < size; i++)
{
ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65)));
builder.Append(ch);
}
if (lowerCase)
return builder.ToString().ToLower();
return builder.ToString();
}
}
- 1
- 2
Посмотрите другие вопросы по меткам c# random или Задайте вопрос