Risposte:
La Random
classe viene utilizzata per creare numeri casuali. (Pseudo-casuale che è ovviamente.).
Esempio:
Random rnd = new Random();
int month = rnd.Next(1, 13); // creates a number between 1 and 12
int dice = rnd.Next(1, 7); // creates a number between 1 and 6
int card = rnd.Next(52); // creates a number between 0 and 51
Se hai intenzione di creare più di un numero casuale, dovresti conservare l' Random
istanza e riutilizzarla. Se si creano nuove istanze troppo vicine nel tempo, produrranno la stessa serie di numeri casuali del generatore casuale generato dall'orologio di sistema.
rnd
come static
e / o impostarlo una sola volta durante l'inizializzazione del codice.
Random
...
Random
rendere la tua casualità più solida: ericlippert.com/2019/02/04/fixing-random-part-2 e codeblog.jonskeet.uk/2009/11/04/revisiting casualità .
La domanda sembra molto semplice ma la risposta è un po 'complicata. Se vedi quasi tutti hanno suggerito di usare la classe Random e alcuni hanno suggerito di usare la classe crypto RNG. Ma poi quando scegliere cosa.
Per questo dobbiamo prima capire il termine RANDOMNESS e la filosofia che sta dietro.
Ti incoraggio a guardare questo video che approfondisce la filosofia di RANDOMNESS usando C # https://www.youtube.com/watch?v=tCYxc-2-3fY
Per prima cosa cerchiamo di capire la filosofia della RANDOMNESS. Quando diciamo a una persona di scegliere tra ROSSO, VERDE e GIALLO cosa succede internamente. Cosa fa scegliere una persona ROSSO, GIALLO o VERDE?
Qualche pensiero iniziale va nella mente delle persone che decide la sua scelta, può essere il colore preferito, il colore fortunato e così via. In altre parole, un trigger iniziale che definiamo RANDOM come SEED. Questo SEED è il punto di partenza, il trigger che lo spinge a selezionare il valore RANDOM.
Ora, se un SEME è facile da indovinare, allora quel tipo di numeri casuali è definito come PSEUDO e quando un seme è difficile da indovinare quei numeri casuali sono chiamati numeri casuali SICURI .
Ad esempio, una persona sceglie il colore in base al tempo e alla combinazione di suoni, quindi sarebbe difficile indovinare il seme iniziale.
Ora lasciami fare una dichiarazione importante: -
* La classe "Random" genera solo numeri casuali PSEUDO e per generare un numero casuale SICURO è necessario utilizzare la classe "RNGCryptoServiceProvider".
La classe casuale prende i valori di seed dal clock della CPU che è molto prevedibile. Quindi in altre parole la classe RANDOM di C # genera numeri pseudo casuali, di seguito è riportato il codice per lo stesso.
** Nota: ** .NET Core 2.0.0+
utilizza un seme diverso sul costruttore senza parametri: al posto del clock della CPU utilizza Guid.NewGuid().GetHashCode()
.
var random = new Random();
int randomnumber = random.Next()
Mentre la RNGCryptoServiceProvider
classe utilizza l'entropia del sistema operativo per generare seed. L'entropia del sistema operativo è un valore casuale che viene generato utilizzando il suono, il clic del mouse, i tempi della tastiera, la temperatura termica, ecc. Di seguito viene riportato il codice per lo stesso.
using (RNGCryptoServiceProvider rg = new RNGCryptoServiceProvider())
{
byte[] rno = new byte[5];
rg.GetBytes(rno);
int randomvalue = BitConverter.ToInt32(rno, 0);
}
Per comprendere l'entropia del sistema operativo vedere questo video dalle 14:30 https://www.youtube.com/watch?v=tCYxc-2-3fY in cui viene spiegata la logica dell'entropia del sistema operativo. Quindi, mettendo in parole semplici RNG Crypto genera numeri casuali SICURI.
RandomNumberGenerator.Create()
invece di chiamare il costruttore di RNGCryptoServiceProvider
poiché non è disponibile su tutte le piattaforme.
Ogni volta che fai nuovo Random () viene inizializzato. Ciò significa che in un ciclo stretto si ottiene lo stesso valore molte volte. Dovresti conservare una singola istanza casuale e continuare a usare Next nella stessa istanza.
//Function to get random number
private static readonly Random getrandom = new Random();
public static int GetRandomNumber(int min, int max)
{
lock(getrandom) // synchronize
{
return getrandom.Next(min, max);
}
}
Random
oggetto. In entrambi i casi ho ottenuto lo stesso numero casuale. Con l'approccio di Pankaj non è successo. Forse è casuale , ma ora ne dubito. Sto chiedendo il numero casuale nello stesso secondo da thread diversi.
Attenzione che new Random()
viene trasmesso sul timestamp corrente.
Se vuoi generare un solo numero puoi usare:
new Random().Next( int.MinValue, int.MaxValue )
Per ulteriori informazioni, guarda la classe Casuale , tuttavia tieni presente che:
Tuttavia, poiché l'orologio ha una risoluzione limitata, l'utilizzo del costruttore senza parametri per creare diversi oggetti casuali in successione ravvicinata crea generatori di numeri casuali che producono sequenze identiche di numeri casuali
Quindi non utilizzare questo codice per generare una serie di numeri casuali.
new Random()
in un ciclo sia un punto importante.
Volevo aggiungere una versione crittograficamente sicura:
Classe RNGCryptoServiceProvider ( MSDN o dotnetperls )
Implementa IDisposable.
using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider())
{
byte[] randomNumber = new byte[4];//4 for int32
rng.GetBytes(randomNumber);
int value = BitConverter.ToInt32(randomNumber, 0);
}
Puoi usare il metodo StaticRandom di Jon Skeet all'interno della libreria di classi MiscUtil che ha creato per un numero pseudo-casuale.
using MiscUtil;
...
for (int i = 0; i < 100;
Console.WriteLine(StaticRandom.Next());
Ho provato tutte queste soluzioni esclusa la risposta COBOL ... lol
Nessuna di queste soluzioni era abbastanza buona. Avevo bisogno di randoms in un ciclo veloce per int e stavo ottenendo tonnellate di valori duplicati anche in intervalli molto ampi. Dopo essermi accontentato di risultati casuali per troppo tempo, ho deciso di affrontare finalmente questo problema una volta per tutte.
Riguarda il seme.
Creo un numero intero casuale analizzando le non cifre da Guid, quindi lo utilizzo per creare un'istanza della mia classe Random.
public int GenerateRandom(int min, int max)
{
var seed = Convert.ToInt32(Regex.Match(Guid.NewGuid().ToString(), @"\d+").Value);
return new Random(seed).Next(min, max);
}
Aggiornamento : il seeding non è necessario se si crea un'istanza della classe Random una volta. Quindi sarebbe meglio creare una classe statica e annullare un metodo.
public static class IntUtil
{
private static Random random;
private static void Init()
{
if (random == null) random = new Random();
}
public static int Random(int min, int max)
{
Init();
return random.Next(min, max);
}
}
Quindi puoi usare la classe statica in questo modo ..
for(var i = 0; i < 1000; i++)
{
int randomNumber = IntUtil.Random(1,100);
Console.WriteLine(randomNumber);
}
Ammetto che mi piace meglio questo approccio.
I numeri generati dalla Random
classe incorporata (System.Random) generano numeri pseudo casuali.
Se vuoi veri numeri casuali, il più vicino che possiamo ottenere è "generatore pseudo-casuale sicuro" che può essere generato usando le classi crittografiche in C # come RNGCryptoServiceProvider
.
Tuttavia, se hai ancora bisogno di veri numeri casuali, dovrai utilizzare una fonte esterna come dispositivi che tengono conto del decadimento radioattivo come seme per un generatore di numeri casuali. Poiché, per definizione, qualsiasi numero generato con mezzi puramente algoritmici non può essere veramente casuale.
creare un oggetto casuale
Random rand = new Random();
e usalo
int randomNumber = rand.Next(min, max);
non è necessario inizializzare new Random()
ogni volta che è necessario un numero casuale, avviare un numero casuale quindi utilizzarlo tutte le volte che è necessario all'interno di un ciclo o qualsiasi altra cosa
new Random()
usa i tick correnti come seed. Quando si istanziano più istanze nello stesso millisecondo (invece che spuntare), si otterrà lo stesso valore restituito.
Risposta modificata da qui .
Se hai accesso a una CPU compatibile con Intel Secure Key, puoi generare numeri e stringhe casuali reali utilizzando queste librerie: https://github.com/JebteK/RdRand e https://www.rdrand.com/
Basta scaricare l'ultima versione da qui , includere Jebtek.RdRand e aggiungere un'istruzione using per esso. Quindi, tutto ciò che devi fare è questo:
// Check to see if this is a compatible CPU
bool isAvailable = RdRandom.GeneratorAvailable();
// Generate 10 random characters
string key = RdRandom.GenerateKey(10);
// Generate 64 random characters, useful for API keys
string apiKey = RdRandom.GenerateAPIKey();
// Generate an array of 10 random bytes
byte[] b = RdRandom.GenerateBytes(10);
// Generate a random unsigned int
uint i = RdRandom.GenerateUnsignedInt();
Se non si dispone di una CPU compatibile per eseguire il codice, utilizzare i servizi RESTful su rdrand.com. Con la libreria wrapper RdRandom inclusa nel tuo progetto, dovrai solo farlo (ricevi 1000 chiamate gratuite al momento dell'iscrizione):
string ret = Randomizer.GenerateKey(<length>, "<key>");
uint ret = Randomizer.GenerateUInt("<key>");
byte[] ret = Randomizer.GenerateBytes(<length>, "<key>");
Mentre questo va bene:
Random random = new Random();
int randomNumber = random.Next()
Dovresti controllare il limite (mumbers min e max) per la maggior parte del tempo. Quindi è necessario specificare dove inizia e finisce il numero casuale.
Il Next()
metodo accetta due parametri, min e max.
Quindi, se voglio che il mio numero casuale sia compreso tra 5 e 15, lo farei
int randomNumber = random.Next(5, 16)
Questa è la classe che uso. Funziona comeRandomNumber.GenerateRandom(1, 666)
internal static class RandomNumber
{
private static Random r = new Random();
private static object l = new object();
private static Random globalRandom = new Random();
[ThreadStatic]
private static Random localRandom;
public static int GenerateNewRandom(int min, int max)
{
return new Random().Next(min, max);
}
public static int GenerateLockedRandom(int min, int max)
{
int result;
lock (RandomNumber.l)
{
result = RandomNumber.r.Next(min, max);
}
return result;
}
public static int GenerateRandom(int min, int max)
{
Random random = RandomNumber.localRandom;
if (random == null)
{
int seed;
lock (RandomNumber.globalRandom)
{
seed = RandomNumber.globalRandom.Next();
}
random = (RandomNumber.localRandom = new Random(seed));
}
return random.Next(min, max);
}
}
Volevo dimostrare cosa succede quando un nuovo generatore casuale viene utilizzato ogni volta. Supponiamo di avere due metodi o due classi, ciascuno dei quali richiede un numero casuale. E ingenuamente li codifichi come:
public class A
{
public A()
{
var rnd=new Random();
ID=rnd.Next();
}
public int ID { get; private set; }
}
public class B
{
public B()
{
var rnd=new Random();
ID=rnd.Next();
}
public int ID { get; private set; }
}
Pensi che otterrai due ID diversi? NO
class Program
{
static void Main(string[] args)
{
A a=new A();
B b=new B();
int ida=a.ID, idb=b.ID;
// ida = 1452879101
// idb = 1452879101
}
}
La soluzione è utilizzare sempre un singolo generatore casuale statico. Come questo:
public static class Utils
{
public static readonly Random random=new Random();
}
public class A
{
public A()
{
ID=Utils.random.Next();
}
public int ID { get; private set; }
}
public class B
{
public B()
{
ID=Utils.random.Next();
}
public int ID { get; private set; }
}
RNGCryptoServiceProvider
è comunque una chiamata migliore.
Per un forte seme casuale uso sempre CryptoRNG e non Time.
using System;
using System.Security.Cryptography;
public class Program
{
public static void Main()
{
var random = new Random(GetSeed());
Console.WriteLine(random.Next());
}
public static int GetSeed()
{
using (var rng = new RNGCryptoServiceProvider())
{
var intBytes = new byte[4];
rng.GetBytes(intBytes);
return BitConverter.ToInt32(intBytes, 0);
}
}
}
Random random = new Random ();
int randomNumber = random.Next (lowerBound,upperBound);
Proprio come una nota per riferimento futuro.
Se stai usando .NET Core, più istanze casuali non sono così pericolose come prima. Sono consapevole che questa domanda è del 2010, ma poiché questa domanda è vecchia ma ha qualche attrazione, penso che sia una buona cosa documentare il cambiamento.
Puoi fare riferimento a questa domanda che ho fatto tempo fa:
Microsoft ha modificato il seed predefinito casuale?
Fondamentalmente, hanno cambiato il seed predefinito da Environment.TickCount
a Guid.NewGuid().GetHashCode()
, quindi se crei 2 istanze di Random non visualizzerà gli stessi numeri.
Puoi vedere le differenze tra i file da .NET Framework / .NET Core (2.0.0+) qui: https://github.com/dotnet/coreclr/pull/2192/commits/9f6a0b675e5ac0065a268554de49162c539ff66d
Non è sicuro come RNGCryptoServiceProvider, ma almeno non ti darà risultati strani.
Interop.GetRandomBytes((byte*)&result, sizeof(int));
.
I numeri calcolati da un computer attraverso un processo deterministico, per definizione, non possono essere casuali.
Se si desidera un vero numero casuale, la casualità deriva dal rumore atmosferico o dal decadimento radioattivo.
Puoi provare ad esempio RANDOM.ORG (riduce le prestazioni)
Random rand = new Random();
int name = rand.Next()
Inserisci i valori che vuoi tra parentesi seconde assicurati di aver impostato un nome scrivendo prop e double tab per generare il codice
Se vuoi che un CSRNG generi numeri casuali tra un minimo e un massimo, questo è per te. Inizializzerà le Random
classi con seed casuali sicuri.
class SecureRandom : Random
{
public static byte[] GetBytes(ulong length)
{
RNGCryptoServiceProvider RNG = new RNGCryptoServiceProvider();
byte[] bytes = new byte[length];
RNG.GetBytes(bytes);
RNG.Dispose();
return bytes;
}
public SecureRandom() : base(BitConverter.ToInt32(GetBytes(4), 0))
{
}
public int GetRandomInt(int min, int max)
{
int treashold = max - min;
if(treashold != Math.Abs(treashold))
{
throw new ArithmeticException("The minimum value can't exceed the maximum value!");
}
if (treashold == 0)
{
throw new ArithmeticException("The minimum value can't be the same as the maximum value!");
}
return min + (Next() % treashold);
}
public static int GetRandomIntStatic(int min, int max)
{
int treashold = max - min;
if (treashold != Math.Abs(treashold))
{
throw new ArithmeticException("The minimum value can't exceed the maximum value!");
}
if(treashold == 0)
{
throw new ArithmeticException("The minimum value can't be the same as the maximum value!");
}
return min + (BitConverter.ToInt32(GetBytes(4), 0) % treashold);
}
}
Spiacenti, OP richiede effettivamente un int
valore casuale , ma per il semplice scopo di condividere la conoscenza se si desidera un BigInteger
valore casuale è possibile utilizzare la seguente istruzione:
BigInteger randomVal = BigInteger.Abs(BigInteger.Parse(Guid.NewGuid().ToString().Replace("-",""), NumberStyles.AllowHexSpecifier));
Presumo che tu voglia un generatore di numeri casuali distribuito uniformemente come di seguito. Il numero casuale nella maggior parte del linguaggio di programmazione, inclusi C # e C ++, non viene mischiato correttamente prima di usarli. Ciò significa che otterrai sempre lo stesso numero, il che non è davvero casuale. Per evitare di disegnare sempre lo stesso numero, è necessario un seme. In genere, i tick in time sono ok per questa attività. Ricorda che otterrai lo stesso numero più volte se stai usando lo stesso seme ogni volta. Quindi cerca di usare sempre semi diversi. Il tempo è una buona fonte per i semi perché si rincorrono sempre.
int GetRandomNumber(int min, int max)
{
Random rand = new Random((int)DateTime.Now.Ticks);
return rand.Next(min, max);
}
se stai cercando un generatore di numeri casuali per la distribuzione normale, potresti usare una trasformazione Box-Muller. Controlla la risposta di yoyoyoyosef nella Domanda variabile gaussiana casuale. Dato che vuoi un numero intero, devi lanciare il doppio valore in numero intero alla fine.
Random rand = new Random(); //reuse this if you are generating many
double u1 = 1.0-rand.NextDouble(); //uniform(0,1] random doubles
double u2 = 1.0-rand.NextDouble();
double randStdNormal = Math.Sqrt(-2.0 * Math.Log(u1)) *
Math.Sin(2.0 * Math.PI * u2); //random normal(0,1)
double randNormal =
mean + stdDev * randStdNormal; //random normal(mean,stdDev^2)
Il modo più semplice è probabilmente solo Random.range(1, 3)
Questo genererebbe un numero compreso tra 1 e 2.
Puoi provare con un valore seme casuale usando di seguito:
var rnd = new Random(11111111); //note: seed value is 11111111
string randomDigits = rnd.Next();
var requestNumber = $"SD-{randomDigits}";
Perché non usare int randomNumber = Random.Range(start_range, end_range)
?
Utilizzare ripetutamente un'istanza di Casuale
// Somewhat better code...
Random rng = new Random();
for (int i = 0; i < 100; i++)
{
Console.WriteLine(GenerateDigit(rng));
}
...
static int GenerateDigit(Random rng)
{
// Assume there'd be more logic here really
return rng.Next(10);
}
Questo articolo esamina perché la casualità causa così tanti problemi e come risolverli. http://csharpindepth.com/Articles/Chapter12/Random.aspx
Random
non è una classe thread-safe. Se si crea una singola istanza, è necessario limitare l'accesso ad essa dietro un meccanismo di blocco.
Prova questi semplici passaggi per creare numeri casuali:
Crea funzione:
private int randomnumber(int min, int max)
{
Random rnum = new Random();
return rnum.Next(min, max);
}
Utilizzare la funzione sopra in una posizione in cui si desidera utilizzare numeri casuali. Supponiamo che tu voglia usarlo in una casella di testo.
textBox1.Text = randomnumber(0, 999).ToString();
0 è min e 999 è max. È possibile modificare i valori come desiderato.
Ho sempre metodi che generano numeri casuali che aiutano per vari scopi. Spero che questo possa aiutare anche te:
public class RandomGenerator
{
public int RandomNumber(int min, int max)
{
var random = new Random();
return random.Next(min, max);
}
public string RandomString(int size, bool lowerCase)
{
var builder = new StringBuilder();
var random = new Random();
char ch;
for (int i = 0; i < size; i++)
{
ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65)));
builder.Append(ch);
}
if (lowerCase)
return builder.ToString().ToLower();
return builder.ToString();
}
}
Veloce e facile per in linea, utilizzare il codice seguente:
new Random().Next(min, max);
// for example unique name
strName += "_" + new Random().Next(100, 999);