Генерация случайных значений в C # - PullRequest
32 голосов
/ 24 марта 2009

Как я могу генерировать случайные значения Int64 и UInt64, используя класс Random в C #?

Ответы [ 9 ]

73 голосов
/ 24 марта 2009

Это должно сработать. (Это метод расширения, так что вы можете вызывать его так же, как вы вызываете обычные Next или NextDouble методы для объекта Random).

public static Int64 NextInt64(this Random rnd)
{
    var buffer = new byte[sizeof(Int64)];
    rnd.NextBytes(buffer);
    return BitConverter.ToInt64(buffer, 0);
}

Просто замените Int64 на UInt64 везде, если хотите вместо этого целые числа без знака, и все должно работать нормально.

Примечание: Поскольку не было предоставлено никакого контекста относительно безопасности или желаемой случайности сгенерированных чисел (на самом деле OP специально упомянул класс Random), мой пример просто касается класса Random , который является предпочтительным решением, когда случайность (часто определяемая как информационная энтропия ) не является проблемой. Для интереса посмотрите другие ответы, в которых упоминается RNGCryptoServiceProvider (ГСЧ, предоставленный в пространстве имен System.Security), который можно использовать почти одинаково.

29 голосов
/ 24 марта 2009

Использование Random.NextBytes() и BitConverter.ToInt64 / BitConverter.ToUInt64.

// Assume rng refers to an instance of System.Random
byte[] bytes = new byte[8];
rng.NextBytes(bytes);
long int64 = BitConverter.ToInt64(bytes, 0);
ulong uint64 = BitConverter.ToUInt64(bytes, 0);

Обратите внимание, что использование Random.Next() дважды, смещение одного значения и затем ИЛИ / добавление не работает. Random.Next() производит только неотрицательные целые числа, т. Е. Генерирует 31 бит, а не 32, поэтому в результате двух вызовов получается только 62 случайных бита вместо 64 битов, необходимых для охвата всего диапазона Int64 / UInt64. ( Ответ Гуффы показывает, как это сделать с помощью трех вызовов Random.Next().)

9 голосов
/ 24 марта 2009

Итак, здесь используются криптосервисы (не класс Random) , что (теоретически) лучше, чем RNG, чем класс Random. Вы можете легко сделать это расширением Random или создать свой собственный класс Random, где RNGCryptoServiceProvider является объектом уровня класса.

using System.Security.Cryptography;
public static Int64 NextInt64()
{
   var bytes = new byte[sizeof(Int64)];    
   RNGCryptoServiceProvider Gen = new RNGCryptoServiceProvider();
   Gen.GetBytes(bytes);    
   return BitConverter.ToInt64(bytes , 0);        
}
6 голосов
/ 24 марта 2009

Вы можете использовать битовое смещение, чтобы собрать 64-битное случайное число из 31-битного случайного числа, но вы должны использовать три 31-битных числа, чтобы получить достаточно битов:

long r = rnd.Next();
r <<= 31;
r |= rnd.Next();
r <<= 31;
r |= rnd.Next();
5 голосов
/ 24 марта 2009

Я всегда использую это для получения моего случайного начального числа (для краткости удалена проверка ошибок):

m_randomURL = "https://www.random.org/cgi-bin/randnum?num=1&min=1&max=1000000000";
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(m_randomURL);
StreamReader stIn = new StreamReader(req.GetResponse().GetResponseStream());
Random rand = new Random(Convert.ToInt32(stIn.ReadToEnd()));

random.org использует атмосферный шум для генерации случайности и, по-видимому, используется для лотерей и тому подобного.

3 голосов
/ 24 марта 2009

Вы не говорите, как собираетесь использовать эти случайные числа ... имейте в виду, что значения, возвращаемые Случайным , не являются "криптографически безопасными", и их не следует использовать для каких-либо вещей с участием (больших) секретов или (больших) денег.

1 голос
/ 24 марта 2009

Вы можете создать массив byte, заполнить его случайными данными и затем преобразовать в long (Int64) и ulong (* 1 010 *). * * +1011

byte[] buffer = new byte[sizeof(Int64)];
Random random = new Random();

random.NextBytes(buffer);
long signed = BitConverter.ToInt64(buffer, 0);

random.NextBytes(buffer);
long unsigned = BitConverter.ToUInt64(buffer, 0);
0 голосов
/ 20 декабря 2017

Еще один ответ с RNGCryptoServiceProvider вместо Random. Здесь вы можете увидеть, как удалить MSB, чтобы результат всегда был положительным.

public static Int64 NextInt64()
{
    var buffer = new byte[8];
    new RNGCryptoServiceProvider().GetBytes(buffer);
    return BitConverter.ToInt64(buffer, 0) & 0x7FFFFFFFFFFFFFFF;
}
0 голосов
/ 27 марта 2009
Random r=new Random();
int j=r.next(1,23);
Console.WriteLine(j);
...