Как я могу генерировать случайные значения Int64 и UInt64, используя класс Random
в С#?
Генерировать случайные значения в С#
Ответ 1
Это должно сделать трюк. (Это метод расширения, позволяющий вызывать его так же, как вы вызываете обычные методы 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
), который можно использовать почти одинаково.
Ответ 2
Используйте 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()
дважды, сдвигая одно значение, а затем ORing/add не работает. Random.Next()
генерирует только неотрицательные целые числа, т.е. генерирует 31 бит, а не 32, поэтому результат двух вызовов вызывает только 62 случайных бита вместо 64 бит, необходимых для охвата всего диапазона Int64
/UInt64
. (Ответ Guffa показывает, как это сделать с тремя вызовами Random.Next()
.)
Ответ 3
Здесь вы идете, это использует услуги crytpo (а не класс 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);
}
Ответ 4
Вы можете использовать бит-сдвиг, чтобы собрать 64-битное случайное число из 31-битных случайных чисел, но вам нужно использовать три 31-битных номера, чтобы получить достаточное количество бит:
long r = rnd.Next();
r <<= 31;
r |= rnd.Next();
r <<= 31;
r |= rnd.Next();
Ответ 5
Я всегда использую это, чтобы получить мое случайное семя (проверка ошибок удалена для краткости):
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 использует атмосферный шум для генерации случайности и, по-видимому, используется для лотерей и т.д.
Ответ 6
Вы не говорите, как вы собираетесь использовать эти случайные числа... имейте в виду, что значения, возвращаемые Random, не являются "криптографически безопасными", и они не должны использоваться для вещей, связанных с (большими) секретами или (много) денег.
Ответ 7
Вы можете создать массив 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);
Ответ 8
Другой ответ с RNGCryptoServiceProvider
вместо Random
. Здесь вы можете увидеть, как удалить MSB, чтобы результат всегда был положительным.
public static Int64 NextInt64()
{
var buffer = new byte[8];
new RNGCryptoServiceProvider().GetBytes(buffer);
return BitConverter.ToInt64(buffer, 0) & 0x7FFFFFFFFFFFFFFF;
}
Ответ 9
Random r=new Random();
int j=r.next(1,23);
Console.WriteLine(j);