it-roy-ru.com

Генерация случайных значений в C #

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

32
SyncMaster

Это должно сделать свое дело. (Это метод расширения, так что вы можете вызывать его так же, как вы вызываете обычные методы 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 (RNG, предоставленный в пространстве имен System.Security), который можно использовать почти одинаково.

73
Noldorin

Используйте 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 битов, требуемых для охвата всего диапазона Int64UInt64. ( ответ Гуффы показывает, как это сделать с помощью _/трех вызовов Random.Next().)

29
Jon Skeet

Вот, пожалуйста, здесь используются crytpo services (не класс 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);        
}
9
Muad'Dib

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

long r = rnd.Next();
r <<= 31;
r |= rnd.Next();
r <<= 31;
r |= rnd.Next();
6
Guffa

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

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 использует атмосферный шум для генерации случайности и, по-видимому, используется для лотерей и тому подобного.

5
sipwiz

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

3
Ðаn

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

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);
1
Samuel

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

public static Int64 NextInt64()
{
    var buffer = new byte[8];
    new RNGCryptoServiceProvider().GetBytes(buffer);
    return BitConverter.ToInt64(buffer, 0) & 0x7FFFFFFFFFFFFFFF;
}
0
sventevit