Gerar valores aleatórios em C #
-
21-08-2019 - |
Pergunta
Como posso gerar valores aleatórios Int64 e UInt64 usando a classe Random
em C #?
Solução
Isso deve fazer o truque. (É um método de extensão para que você possa chamá-lo apenas como você chamar os Next
ou NextDouble
métodos normais em um objeto Random
).
public static Int64 NextInt64(this Random rnd)
{
var buffer = new byte[sizeof(Int64)];
rnd.NextBytes(buffer);
return BitConverter.ToInt64(buffer, 0);
}
Basta substituir Int64
com UInt64
em todos os lugares, se você quiser números inteiros sem sinal, em vez e tudo deve funcionar bem.
Nota: Uma vez que nenhum contexto foi fornecido sobre a segurança ou a aleatoriedade desejada dos números gerados (na verdade, o OP mencionou especificamente a classe Random
), meu exemplo simplesmente lida com a classe Random
, que é a solução preferida quando aleatoriedade (frequentemente quantificada como informações entropia ) não é um problema. Por uma questão de interesse, consulte as outras respostas que RNGCryptoServiceProvider
menção (RNG fornecido no namespace System.Security
), que pode ser usado de forma quase idêntica.
Outras dicas
Use Random.NextBytes()
e 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);
Note que o uso Random.Next()
duas vezes, mudando um valor e, em seguida, ORing / acrescentando não funciona. Random.Next()
só produz inteiros não negativos, isto é, que gera 31 bits, não 32, de modo que o resultado de duas chamadas apenas produz 62 bits aleatórios em vez dos 64 bits requeridos para cobrir a gama completa de Int64
/ UInt64
. (A resposta de Guffa mostra como fazê-lo com três chamadas para Random.Next()
embora.)
Aqui está, este usa o serviços crytpo (não a classe Random) , que é (teoricamente) uma melhor RNG então a classe Random. Você poderia facilmente fazer isso uma extensão da Random ou fazer a sua própria classe Random onde o RNGCryptoServiceProvider é um objeto de nível de classe.
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);
}
Você pode usar o deslocamento pouco para montar um 64 bit número aleatório de 31 bits números aleatórios, mas você tem que usar três 31 números de bits para obter bits suficientes:
long r = rnd.Next();
r <<= 31;
r |= rnd.Next();
r <<= 31;
r |= rnd.Next();
Eu sempre uso isso para obter a minha semente aleatória (verificação de erro removido por brevidade):
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 usa ruído atmosférico para gerar a aleatoriedade e é aparentemente usado para loterias e tal.
Você não diz como você está indo para usar esses números aleatórios ... ter em mente que os valores devolvidos pela Aleatório não são "criptograficamente seguro" e não devem ser utilizados para coisas que envolvem (grandes) segredos ou (lotes de) dinheiro.
Você pode criar uma matriz byte
, preenchê-lo com aleatório de dados e, em seguida, convertê-lo para long
(Int64
) e 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);
Outra resposta com RNGCryptoServiceProvider
vez de Random
. Aqui você pode ver como remover o MSB de modo que o resultado é sempre positivo.
public static Int64 NextInt64()
{
var buffer = new byte[8];
new RNGCryptoServiceProvider().GetBytes(buffer);
return BitConverter.ToInt64(buffer, 0) & 0x7FFFFFFFFFFFFFFF;
}
Random r=new Random();
int j=r.next(1,23);
Console.WriteLine(j);