2009-03-24 6 views

ответ

72

Это должно сделать трюк. (Это метод расширения, так что вы можете называть его так же, как вы вызываете обычные методы 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 везде, если вы хотите, целые числа без знака, а и все должно работать нормально.

Примечание: Поскольку ни один контекст не был предоставлен в отношении безопасности или желаемой случайности генерируемых чисел (на самом деле ОП конкретно упоминается Random класса), мой пример просто имеет дело с Random класса, который является предпочтительным решением, когда случайность (часто определяется как information entropy) не является проблемой. В качестве интереса см. Другие ответы, в которых упоминается RNGCryptoServiceProvider (RNG, предоставленный в пространстве имен System.Security), который можно использовать почти одинаково.

+1

+1 для того, чтобы дать ОП то, что они просили, а также упомянуть ограничения использования Random и предложить альтернативу, если ограничения Random слишком ограничены для предполагаемого использования. – JeffH

+5

Обратите внимание, что этот подход также возвращает отрицательные числа и Int64.MaxValue, тогда как System.Random.Next() привязан к положительным числам, включая 0, но без Int32.MaxValue. –

+0

@ Кристоф: Да, хорошо видно.Однако вы могли бы довольно легко модифицировать мой метод, чтобы создавать положительные значения, игнорируя MSB (самый старший бит) буфера. – Noldorin

29

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/добавление не работает. Random.Next() создает только неотрицательные целые числа, то есть генерирует 31 бит, а не 32, поэтому результат двух вызовов генерирует только 62 случайных бита вместо 64 бит, необходимых для охвата всего диапазона Int64/UInt64. (Guffa's answer показывает, как это сделать с три звонки на Random.Next().)

+0

О, хороший улов (комментарий) - я удалить мой, как BitConverter и т.д. уже хорошо покрыты ... –

+0

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

+0

В связи с тем, что большинство lcm PRNG менее случайны в битах младшего порядка, генерируя 2 числа и соединяя их вместе, могут вводить тонкие предубеждения ... –

1

Вы можете создать 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); 
3

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

+0

-1 для не упоминания .Net Crypto RNG. http://msdn.microsoft.com/en-us/library/system.security.cryptography.rngcryptoserviceprovider.aspx – Samuel

+0

Почему это релевантно? Дэн ссылается на то, что ПК не может генерировать криптографически безопасное случайное число. Класс RNGCryptoServiceProvider не исправляет это. – sipwiz

+0

Нет, он сказал, что класс Random не может этого сделать, он ничего не сказал о компьютерах, которые не могут. – Samuel

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

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

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

Здесь вы идете, это использует 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);   
} 
+0

Это, безусловно, стоит отметить, хотя, судя по этому вопросу, OP, похоже, не слишком заботится о случайности сгенерированных чисел. Также важно понимать, что RNGCryptoServiceProvider * намного медленнее, чем Random (хотя производительность может или не имеет значения здесь). – Noldorin

-3
Random r=new Random(); 
int j=r.next(1,23); 
Console.WriteLine(j); 
+0

случайный класс используется для случайного выбора va Класс lues.random предоставляет среду окружения пользователю, чтобы сделать это – 2009-03-27 17:32:16

0

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

public static Int64 NextInt64() 
{ 
    var buffer = new byte[8]; 
    new RNGCryptoServiceProvider().GetBytes(buffer); 
    return BitConverter.ToInt64(buffer, 0) & 0x7FFFFFFFFFFFFFFF; 
} 
Смежные вопросы