Как мне сгенерировать случайное число int?

1617

Как мне генерировать случайное целое число в С#?

Теги:
random

29 ответов

2038
Лучший ответ

Класс 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 и использовать его повторно. Если вы создаете новые экземпляры слишком близко по времени, они будут производить ту же серию случайных чисел, что и генератор случайных чисел, посеянный из системных часов.

  • 0
    Комментарии не для расширенного обсуждения; этот разговор был перенесен в чат .
  • 101
    Просто примечание для пользователей Unity C #, вы должны указать «System.Random ()», поскольку Unity имеет «UnityEngine.Random ()», что конфликтует (обратите внимание, что «UnityEngine.Random ()» не имеет возможности генерировать случайные номера). Так как Unity не всегда импортирует System по умолчанию, это может вызвать путаницу.
Показать ещё 5 комментариев
188

Каждый раз, когда вы делаете новый 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);
    }
}
  • 2
    Разве это не то, что @Guffa сказал в своем ответе 6 месяцев назад? «Если вы создадите новые экземпляры слишком близко по времени, они будут производить ту же серию случайных чисел»
  • 3
    @ Крис: Ты правильно сказал. В этом я обеспечил реализацию этого. Я думаю, что это хороший способ сделать это. Это работает лучше.
Показать ещё 5 комментариев
184

Вопрос выглядит очень простым, но ответ немного сложен. Если вы видите, почти все предложили использовать класс Random, а некоторые предложили использовать криптографический класс RNG. Но тогда когда выбирать что.

Для этого нам нужно сначала понять термин СЛУЧАЙНОСТЬ и его философию.

Я бы посоветовал вам посмотреть это видео, которое углубляется в философию случайности, используя С# https://www.youtube.com/watch?v=tCYxc-2-3fY

Прежде всего, давайте поймем философию СЛУЧАЙНОСТИ. Когда мы говорим человеку выбирать между КРАСНЫМ, ЗЕЛЕНЫМ и ЖЕЛТЫМ, что происходит внутри. Что заставляет человека выбирать КРАСНЫЙ, ЖЕЛТЫЙ или ЗЕЛЕНЫЙ?

Изображение 948

Некоторая начальная мысль приходит в ум человека, который решает его выбор, это может быть любимый цвет, счастливый цвет и так далее. Другими словами, некоторый начальный триггер, который мы называем в СЛУЧАЙНОМ как SEED. Этот SEED является начальной точкой, триггером, побуждающим его выбрать СЛУЧАЙНОЕ значение.

Теперь, если SEED легко угадать, то такие виды случайных чисел называются PSEUDO, а когда семени трудно угадать, эти случайные числа называются SECURED случайными числами.

Например, человек выбирает цвет в зависимости от сочетания погоды и звука, тогда будет трудно угадать начальное зерно.

Изображение 949

Теперь позвольте мне сделать важное выражение:

* "Случайный" класс генерирует только случайное число PSEUDO, и для генерации БЕЗОПАСНОГО случайного числа нам нужно использовать класс "RNGCryptoServiceProvider".

Изображение 950

Случайный класс берет начальные значения из вашего процессора, что очень предсказуемо. Другими словами, случайный класс С# генерирует псевдослучайные числа, ниже приведен код этого же.

Random rnd= new Random();
int rndnumber = rnd.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 генерирует БЕЗОПАСНЫЕ случайные числа.

  • 4
    не должен быть ваш байт [5] только [4], поскольку ToInt32 анализирует только 4 байта?
  • 0
    Всегда полезно знать, где живут эти классы. System.Security.Cryptography
73

Остерегайтесь того, что new Random() добавляется в текущую метку времени.

Если вы хотите сгенерировать только один номер, вы можете использовать:

new Random().Next( int.MinValue, int.MaxValue )

Для получения дополнительной информации посмотрите на класс Random, хотя, пожалуйста, обратите внимание:

Однако, поскольку часы имеют конечное разрешение, использование конструктора без параметров для создания различных случайных объектов в тесной последовательности создает генераторы случайных чисел, которые создают идентичные последовательности случайных чисел.

Поэтому не используйте этот код для генерации серии случайных чисел.

  • 34
    -1: начальное число по умолчанию основано на времени; сделайте это в цикле, и вы получите очень неслучайные результаты. Вы должны создать один генератор и использовать его для всех своих чисел, а не отдельный генератор каждый раз.
  • 14
    Эй, это несправедливо. Вопрос был в том, как сгенерировать случайное целое число. Никакие петли или серии не были упомянуты.
Показать ещё 1 комментарий
43
Random r = new Random();
int n = r.Next();
23

Я хотел добавить криптографически безопасную версию:

Класс 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);
}
13

Вы можете использовать метод Jon Skeet StaticRandom внутри библиотеки классов MiscUtil, который он построил для псевдослучайного числа.

using System;
using MiscUtil;

class Program
{
    static void Main(string[] args)
    {
        for (int i = 0; i < 100; i++)
        {
            Console.WriteLine(StaticRandom.Next());
        }
    }
}
  • 4
    "действительно случайно"? Как это работает?
  • 25
    Я только что посмотрел на исходный код, и эта функция использует точно такой же механизм случайных чисел, тот, который «включен» в C #, но гарантирует, что один и тот же «начальный» / «материнский объект» используется для всех вызовов. (Мне жаль, что я не знаю терминологию C #. Но я хочу сказать, что эта функция не создает случайных чисел лучше, чем стандартная функция.)
Показать ещё 2 комментария
11

лучше заполнить объект Random текущими миллисекундами, чтобы обеспечить истинное случайное число, и вы почти не найдете дубликаты, использующие его много раз

Random rand = new Random(DateTime.Now.Millisecond);

Обновить

Я знаю, что new Random() использует текущие тики в качестве начального числа, но задание с текущими миллисекундами все еще достаточно хорошо, так как это хороший случайный запуск

Последний оставшийся момент заключается в том, что вам не нужно инициализировать new Random() каждый раз, когда вам нужно случайное число, инициировать один объект Random, затем использовать его столько раз, сколько вам нужно внутри цикла или что-то еще

  • 4
    new Random() использует текущие тики в качестве начального числа. Когда вы создаете несколько экземпляров в течение одной миллисекунды (в отличие от тика), вы получите одно и то же возвращаемое значение.
  • 7
    Это активно плохо. DateTime.Now.Millisecond (в отличие от DateTime.Now.Ticks) - это число от 0 до 999. Если вы создаете новый из них для каждого случайного числа, у вас будет только 1000 возможностей.
9

Я пробовал все эти решения, исключая ответ 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); 
}

Я признаю, что мне нравится этот подход лучше.

  • 4
    Гид не случайный, это не хорошее семя. GUID не дает гарантий относительно случайности, он дает гарантии вокруг уникальности. stackoverflow.com/questions/2621563/...
  • 1
    Guid - хорошее семя. Я использую только цифры в Guid. Попробуйте метод для себя. Поместите это в длинную петлю и посмотрите на результаты для себя.
Показать ещё 3 комментария
6

Я использую ниже код для случайного числа:

var random = new Random((int)DateTime.Now.Ticks);
var randomValue = random.Next(startValue, endValue + 1);
6

Цифры, генерируемые встроенным классом Random (System.Random), генерируют псевдослучайные числа.

Если вам нужны истинные случайные числа, самое близкое, что мы можем получить, это "безопасный псевдослучайный генератор", который может быть сгенерирован с использованием криптографических классов в С#, таких как RNGCryptoServiceProvider.

Тем не менее, если вам все еще нужны истинные случайные числа, вам нужно будет использовать внешний источник, такой как устройства, учитывающие радиоактивный распад, в качестве семени для генератора случайных чисел. Поскольку, по определению, любое число, порожденное чисто алгоритмическими средствами, не может быть по-настоящему случайным.

4
Random random = new Random ();
int randomNumber = random.Next (lowerBound,upperBound);
  • 0
    Хотя этот код может ответить на вопрос, лучше объяснить, как решить проблему, и предоставить код в качестве примера или ссылки. Ответы только на код могут быть запутанными и лишены контекста.
4

Это класс, который я использую. Работает как 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);
    }
}
  • 0
    Ваш класс GenerateRandom никогда не вернет число 666, только 665. Это распространенное заблуждение (особенность) максимального значения Random.Next.
3

Пока все в порядке:

Random random = new Random();
int randomNumber = random.Next()

Вы хотите контролировать ограничение (min и max mumbers) большую часть времени. Поэтому вам нужно указать, где начинается и заканчивается случайное число.

Метод Next() принимает два параметра: min и max.

Итак, если я хочу, чтобы мое случайное число было между 5 и 15, я просто делал

int randomNumber = random.Next(5, 16)
3

Измененный ответ здесь.

Если у вас есть доступ к совместимому с Intel Secure Key процессору, вы можете генерировать реальные случайные числа и строки, используя эти библиотеки: https://github.com/JebteK/RdRand и https://www.rdrand.com/

Просто загрузите последнюю версию из здесь, включите Jebtek.RdRand и добавьте для нее инструкцию using. Затем все, что вам нужно сделать, это следующее:

bool isAvailable = RdRandom.GeneratorAvailable(); //Check to see if this is a compatible CPU
string key = RdRandom.GenerateKey(10); //Generate 10 random characters
string apiKey = RdRandom.GenerateAPIKey(); //Generate 64 random characters, useful for API keys
byte[] b = RdRandom.GenerateBytes(10); //Generate an array of 10 random bytes
uint i = RdRandom.GenerateUnsignedInt() //Generate a random unsigned int

Если у вас нет совместимого процессора для выполнения кода, просто используйте службы RESTful на странице rdrand.com. С библиотекой обертки RdRandom, включенной в ваш проект, вам просто нужно это сделать (вы получаете 1000 бесплатных звонков при регистрации):

string ret = Randomizer.GenerateKey(<length>, "<key>");
uint ret = Randomizer.GenerateUInt("<key>");
byte[] ret = Randomizer.GenerateBytes(<length>, "<key>");
2
Random rand = new Random();
int name = rand.Next()

Поместите любые значения, которые вы хотите во второй круглый скоб убедитесь, что вы установили имя, написав подсказку и двойную вкладку, чтобы сгенерировать код

  • 1
    Опора и двойная вкладка?
  • 2
    добавленная стоимость по сравнению с уже существующими ответами?
Показать ещё 1 комментарий
1

Для сильных случайных семян я всегда использую 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);
        }
    }
}
1

Я хотел продемонстрировать, что происходит, когда новый случайный генератор используется каждый раз. Предположим, у вас есть два метода или два класса, для каждого из которых требуется случайное число. И наивно вы их кодируете, как:

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; }
}
  • 0
    или посеять генератор ..
  • 0
    Как вы можете безопасно выбрать семя тогда?
Показать ещё 2 комментария
1

Числа, вычисленные компьютером через детерминированный процесс, по определению не могут быть случайными.

Если вам нужны настоящие случайные числа, случайность возникает из-за атмосферного шума или радиоактивного распада.

Вы можете попробовать, например, RANDOM.ORG(это снижает производительность)

0

К сожалению, OP действительно требует случайного значения int, но для простой цели обмена знаниями, если вы хотите случайное значение BigInteger вы можете использовать следующее утверждение:

BigInteger randomVal = BigInteger.Abs(BigInteger.Parse(Guid.NewGuid().ToString().Replace("-",""), NumberStyles.AllowHexSpecifier));
0

Используйте один экземпляр 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

  • 0
    Random не является потокобезопасным классом. Если вы создаете один экземпляр, вы должны ограничить доступ к нему за механизм блокировки.
0

У меня всегда есть методы, которые генерируют случайные числа, которые помогают для различных целей. Я надеюсь, что это может помочь вам тоже:

public class RandomGenerator  
{  
    public int RandomNumber(int min, int max)  
    {  
        Random random = new Random();  
        return random.Next(min, max);  
    }  

    public string RandomString(int size, bool lowerCase)  
    {  
        StringBuilder builder = new StringBuilder();  
        Random 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();  
    }  
}
0

Я предполагаю, что вы хотите равномерно распределенный генератор случайных чисел, как показано ниже. Случайные числа в большинстве языков программирования, включая С# и 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)

Случайные гауссовские переменные

0

Быстро и легко для встраивания, используйте ниже код:

new Random().Next(min, max);

// for example unique name
strName += "_" + new Random().Next(100, 999);
0

Вы можете попробовать со случайным начальным значением, используя ниже:

var rnd = new Random(11111111); //note: seed value is 11111111

string randomDigits = rnd.Next().ToString().Substring(0, 8);

var requestNumber = $"SD-{randomDigits}";
  • 0
    Спасибо @ MikaelDúiBolinder, чтобы увидеть этот фрагмент
0

Почему бы не использовать int randomNumber = Random.Range(start_range, end_range)?

  • 0
    На самом деле int randomNumber = Random.Range (start_range, end_range + 1)
  • 2
    Существует ли Random.Range ()? Я не смог найти его в документации MSDN.
Показать ещё 1 комментарий
0

Попробуйте эти простые шаги для создания случайных чисел:

Создать функцию:

private int randomnumber(int min, int max)
{
    Random rnum = new Random();
    return rnum.Next(min, max);
}

Используйте вышеуказанную функцию в месте, где вы хотите использовать случайные числа. Предположим, вы хотите использовать его в текстовом поле.

textBox1.Text = randomnumber(0, 999).ToString();

0 - это минимум, а 999 - это максимум. Вы можете изменить значения на то, что вы хотите.

  • 0
    Это будет возвращать один и тот же номер при многократном вызове, так как использует системное время в качестве начального числа ...
  • 1
    randomnumber (0, 999) никогда не вернет 999. Максимальное значение не включено. Это распространенное недоразумение (особенность) максимального значения Random.Next.
-2

Я надеюсь, что этот код может быть полезен

        public static string GeneratePassword()
    {
        string strPwdchar = "abcdefghijklmnopqrstuvwxyz0123456789#+@&$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;

    }

Играйте с ним... надеюсь, вы сможете получить то, что хотите.

-2
 int n = new Random().Next();

вы также можете дать минимальное и максимальное значение функции Next(). Как

 int n = new Random().Next(5,10);

Ещё вопросы

Сообщество Overcoder
Наверх
Меню