Generowanie losowych wartości w C#

Jak mogę wygenerować losowe wartości Int64 i UInt64 używając klasy Random W C#?

Author: Noldorin, 2009-03-24

9 answers

To powinno załatwić sprawę. (Jest to metoda rozszerzenia, dzięki której można ją wywołać tak, jak zwykłe metody Next lub NextDouble na obiekcie Random).

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

Po prostu zamień Int64 na UInt64 wszędzie, jeśli chcesz zamiast tego niepodpisane liczby całkowite i wszystkie powinny działać dobrze.

Uwaga: ponieważ nie podano kontekstu dotyczącego bezpieczeństwa lub pożądanej losowości generowanych liczb (w rzeczywistości OP konkretnie wspomniał klasę Random), mój przykład po prostu zajmuje się klasa Random, która jest preferowanym rozwiązaniem, gdy losowość (często określana jako Entropia informacyjna ) nie jest problemem. Jako ciekawostkę, zobacz inne odpowiedzi, które wspominają RNGCryptoServiceProvider (RNG podany w przestrzeni nazw System.Security), które mogą być używane niemal identycznie.

 75
Author: Noldorin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-18 06:36:24

Użycie Random.NextBytes() oraz 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);

Zauważ, że używając Random.Next() dwa razy, przesunięcie jednej wartości, a następnie ORing/dodawanie nie działa. Random.Next() wytwarza tylko nieujemne liczby całkowite, tzn. generuje 31 bitów, a nie 32, więc wynik dwóch wywołań wytwarza tylko 62 losowe bity zamiast 64 bitów wymaganych do pokrycia pełnego zakresu Int64/UInt64. (odpowiedź Guffa pokazuje, jak to zrobić za pomocą trzech wywołań do Random.Next().)

 29
Author: Jon Skeet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:31:33

Proszę bardzo, to korzysta z usług crytpo (nie Random klasa) , która jest (teoretycznie) lepszym RNG niż Klasa Losowa. Możesz łatwo zrobić to rozszerzenie Random lub stworzyć własną klasę losową, w której rngcryptoserviceprovider jest obiektem na poziomie klasy.

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);        
}
 10
Author: Muad'Dib,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-04-13 16:41:23

Możesz użyć bit shift, aby złożyć 64-bitową liczbę losową z 31-bitowych liczb losowych, ale musisz użyć trzech 31-bitowych liczb, aby uzyskać wystarczającą ilość bitów:

long r = rnd.Next();
r <<= 31;
r |= rnd.Next();
r <<= 31;
r |= rnd.Next();
 6
Author: Guffa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-24 14:17:28

Zawsze używam tego, aby uzyskać moje losowe ziarno (błąd sprawdzania usunięty dla zwięzłości):

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 wykorzystuje hałas atmosferyczny do generowania losowości i jest najwyraźniej używany do loterii i takich.

 5
Author: sipsorcery,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-27 01:25:44

Nie mówisz, jak zamierzasz użyć tych losowych liczb...należy pamiętać, że wartości zwracane przez Random nie są "zabezpieczone kryptograficznie" i nie powinny być używane do rzeczy obejmujących (duże) tajemnice lub (dużo) pieniądze.

 3
Author: Ðаn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-24 13:36:57

Można utworzyć byte tablicy, wypełnij ją losowymi danymi, a następnie przekonwertuj na long (Int64) lub 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);
 2
Author: Samuel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-04-13 16:42:19

Kolejna odpowiedź z RNGCryptoServiceProvider zamiast Random. Tutaj możesz zobaczyć, jak usunąć MSB, aby wynik był zawsze pozytywny.

public static Int64 NextInt64()
{
    var buffer = new byte[8];
    new RNGCryptoServiceProvider().GetBytes(buffer);
    return BitConverter.ToInt64(buffer, 0) & 0x7FFFFFFFFFFFFFFF;
}
 0
Author: sventevit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-20 08:59:06
Random r=new Random();
int j=r.next(1,23);
Console.WriteLine(j);
 -3
Author: thkala,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-07 01:06:03