Ответы:
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
экземпляр и использовать его повторно. Если вы создаете новые экземпляры слишком близко по времени, они будут производить ту же серию случайных чисел, что и генератор случайных чисел, высеянный из системных часов.
rnd
как static
и / или установить его только один раз при инициализации кода.
Random
...
Random
, которые сделают вашу случайность более надежной: ericlippert.com/2019/02/04/fixing-random-part-2 и codeblog.jonskeet.uk/2009/11/04/revisiting -randomness .
Вопрос выглядит очень простым, но ответ немного сложен. Если вы видите, почти все предложили использовать класс Random, а некоторые предложили использовать крипто-класс RNG. Но тогда когда выбирать что.
Для этого нам нужно сначала понять термин СЛУЧАЙНОСТЬ и его философию.
Я бы посоветовал вам посмотреть это видео, которое углубляется в философию случайности, используя C # https://www.youtube.com/watch?v=tCYxc-2-3fY
Прежде всего, давайте поймем философию СЛУЧАЙНОСТИ. Когда мы говорим человеку выбирать между КРАСНЫМ, ЗЕЛЕНЫМ и ЖЕЛТЫМ, что происходит внутри. Что заставляет человека выбирать красный, желтый или зеленый?
Некоторая начальная мысль приходит в ум человека, который решает его выбор, это может быть любимый цвет, счастливый цвет и так далее. Другими словами, некоторый начальный триггер, который мы называем в СЛУЧАЙНОМ как SEED. Этот SEED является начальной точкой, триггером, побуждающим его выбрать СЛУЧАЙНОЕ значение.
Теперь, если SEED легко угадать, то такие виды случайных чисел называются PSEUDO, а когда семени трудно угадать, эти случайные числа называются SECURED случайными числами.
Например, человек выбирает цвет в зависимости от сочетания погоды и звука, тогда будет сложно угадать начальное зерно.
Теперь позвольте мне сделать важное заявление:
* «Случайный» класс генерирует только случайное число PSEUDO, и для генерации БЕЗОПАСНОГО случайного числа нам нужно использовать класс «RNGCryptoServiceProvider».
Случайный класс берет начальные значения из вашего процессора, что очень предсказуемо. Другими словами, случайный класс C # генерирует псевдослучайные числа, ниже приведен код этого же.
** Примечание: ** .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 генерирует БЕЗОПАСНЫЕ случайные числа.
RandomNumberGenerator.Create()
вместо вызова конструктора, RNGCryptoServiceProvider
поскольку он доступен не на всех платформах.
Каждый раз, когда вы делаете новый 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);
}
}
Random
объект. В обоих случаях я получил одно и то же случайное число. С подходом из Панкаджа этого не произошло. Возможно, это случайно , но я сомневаюсь в этом сейчас. Я запрашиваю случайное число в одну секунду из разных потоков.
Остерегайтесь этого new Random()
посеяно на текущей метке времени.
Если вы хотите сгенерировать только один номер, вы можете использовать:
new Random().Next( int.MinValue, int.MaxValue )
Для получения дополнительной информации посмотрите на класс Random , хотя, пожалуйста, обратите внимание:
Однако, поскольку часы имеют конечное разрешение, использование конструктора без параметров для создания различных случайных объектов в тесной последовательности создает генераторы случайных чисел, которые создают идентичные последовательности случайных чисел.
Поэтому не используйте этот код для генерации серии случайных чисел.
new 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());
Я перепробовал все эти решения, кроме ответа на 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);
}
Я признаю, что мне нравится этот подход лучше.
Числа, генерируемые встроенным Random
классом (System.Random), генерируют псевдослучайные числа.
Если вам нужны истинные случайные числа, то самое близкое, что мы можем получить, - это «безопасный генератор псевдослучайных чисел», который можно сгенерировать с помощью криптографических классов в C #, таких как RNGCryptoServiceProvider
.
Тем не менее, если вам все еще нужны истинные случайные числа, вам нужно будет использовать внешний источник, такой как устройства, учитывающие радиоактивный распад, в качестве начального числа для генератора случайных чисел. Поскольку, по определению, любое число, генерируемое чисто алгоритмическими средствами, не может быть действительно случайным.
создать случайный объект
Random rand = new Random();
и использовать это
int randomNumber = rand.Next(min, max);
вам не нужно инициализировать new Random()
каждый раз, когда вам нужно случайное число, инициировать одно случайное число, а затем использовать его столько раз, сколько вам нужно внутри цикла или что-то еще
new Random()
использует текущие тики в качестве семян. Когда вы создаете несколько экземпляров в течение одной миллисекунды (в отличие от тика), вы получите одно и то же возвращаемое значение.
Модифицированный ответ отсюда .
Если у вас есть доступ к процессору, совместимому с 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 random = new Random();
int randomNumber = random.Next()
Вы бы хотели контролировать лимит (минимальное и максимальное количество) большую часть времени. Таким образом, вам нужно указать, где случайное число начинается и заканчивается.
Next()
Метод принимает два параметра, мин и макс.
Так что, если я хочу, чтобы мое случайное число было между 5 и 15, я бы просто сделал
int randomNumber = random.Next(5, 16)
Это класс, который я использую. Работает как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);
}
}
Я хотел продемонстрировать, что происходит, когда каждый раз используется новый генератор случайных чисел. Предположим, у вас есть два метода или два класса, каждый из которых требует случайного числа. И вы наивно кодируете их так:
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; }
}
Как вы думаете, вы получите два разных идентификатора? НЕТ
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; }
}
RNGCryptoServiceProvider
лучше позвонить в любом случае.
Для сильных случайных семян я всегда использую 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 random = new Random ();
int randomNumber = random.Next (lowerBound,upperBound);
Так же, как примечание для дальнейшего использования.
Если вы используете .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, но по крайней мере он не даст вам странных результатов.
Interop.GetRandomBytes((byte*)&result, sizeof(int));
.
Числа, рассчитанные компьютером с помощью детерминированного процесса, по определению не могут быть случайными.
Если вам нужны настоящие случайные числа, случайность происходит из-за атмосферного шума или радиоактивного распада.
Вы можете попробовать, например, RANDOM.ORG (это снижает производительность)
Random rand = new Random();
int name = rand.Next()
Поместите любые значения во вторые скобки, чтобы убедиться, что вы установили имя, написав prop и double tab для генерации кода.
Если вы хотите, чтобы CSRNG генерировал случайные числа от мин до макс, это для вас. Это инициализирует Random
классы с безопасными случайными семенами.
class SecureRandom : Random
{
public static byte[] GetBytes(ulong length)
{
RNGCryptoServiceProvider RNG = new RNGCryptoServiceProvider();
byte[] bytes = new byte[length];
RNG.GetBytes(bytes);
RNG.Dispose();
return bytes;
}
public SecureRandom() : base(BitConverter.ToInt32(GetBytes(4), 0))
{
}
public int GetRandomInt(int min, int max)
{
int treashold = max - min;
if(treashold != Math.Abs(treashold))
{
throw new ArithmeticException("The minimum value can't exceed the maximum value!");
}
if (treashold == 0)
{
throw new ArithmeticException("The minimum value can't be the same as the maximum value!");
}
return min + (Next() % treashold);
}
public static int GetRandomIntStatic(int min, int max)
{
int treashold = max - min;
if (treashold != Math.Abs(treashold))
{
throw new ArithmeticException("The minimum value can't exceed the maximum value!");
}
if(treashold == 0)
{
throw new ArithmeticException("The minimum value can't be the same as the maximum value!");
}
return min + (BitConverter.ToInt32(GetBytes(4), 0) % treashold);
}
}
Извините, OP действительно требует случайного int
значения, но для простой цели обмена знаниями, если вы хотите случайное BigInteger
значение, вы можете использовать следующее утверждение:
BigInteger randomVal = BigInteger.Abs(BigInteger.Parse(Guid.NewGuid().ToString().Replace("-",""), NumberStyles.AllowHexSpecifier));
Я предполагаю, что вы хотите равномерно распределенный генератор случайных чисел, как показано ниже. Случайные числа в большинстве языков программирования, включая C # и 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)
Возможно, самый простой способ - Random.range(1, 3)
это сгенерировать число от 1 до 2.
Вы можете попробовать со случайным начальным значением, используя ниже:
var rnd = new Random(11111111); //note: seed value is 11111111
string randomDigits = rnd.Next();
var requestNumber = $"SD-{randomDigits}";
Почему бы не использовать int randomNumber = Random.Range(start_range, end_range)
?
Используйте один экземпляр Random несколько раз
// Somewhat better code...
Random rng = new Random();
for (int i = 0; i < 100; i++)
{
Console.WriteLine(GenerateDigit(rng));
}
...
static int GenerateDigit(Random rng)
{
// Assume there'd be more logic here really
return rng.Next(10);
}
В этой статье рассматривается, почему случайность вызывает так много проблем, и как их решать. http://csharpindepth.com/Articles/Chapter12/Random.aspx
Random
не потокобезопасный класс. Если вы создаете один экземпляр, вы должны ограничить доступ к нему за механизм блокировки.
Попробуйте эти простые шаги для создания случайных чисел:
Создать функцию:
private int randomnumber(int min, int max)
{
Random rnum = new Random();
return rnum.Next(min, max);
}
Используйте вышеуказанную функцию в месте, где вы хотите использовать случайные числа. Предположим, вы хотите использовать его в текстовом поле.
textBox1.Text = randomnumber(0, 999).ToString();
0 - это минимум, а 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();
}
}
Быстро и легко для встраивания, используйте ниже код:
new Random().Next(min, max);
// for example unique name
strName += "_" + new Random().Next(100, 999);