Réponses:
La Random
classe est utilisée pour créer des nombres aléatoires. (Pseudo-aléatoire, bien sûr.).
Exemple:
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
Si vous souhaitez créer plusieurs nombres aléatoires, vous devez conserver l' Random
instance et la réutiliser. Si vous créez de nouvelles instances trop proches dans le temps, elles produiront la même série de nombres aléatoires que le générateur aléatoire est issu de l'horloge système.
rnd
comme static
et / ou le définir une seule fois lors de l'initialisation du code.
Random
...
Random
faire pour rendre votre aléatoire plus robuste: ericlippert.com/2019/02/04/fixing-random-part-2 et codeblog.jonskeet.uk/2009/11/04/revisiting -la aléatoire .
La question semble très simple mais la réponse est un peu compliquée. Si vous voyez, presque tout le monde a suggéré d'utiliser la classe Random et certains ont suggéré d'utiliser la classe de chiffrement RNG. Mais alors quand choisir quoi.
Pour cela, nous devons d'abord comprendre le terme RANDOMNESS et la philosophie qui le sous-tend.
Je vous encourage à regarder cette vidéo qui approfondit la philosophie de RANDOMNESS en utilisant C # https://www.youtube.com/watch?v=tCYxc-2-3fY
Tout d'abord, comprenons la philosophie de RANDOMNESS. Lorsque nous disons à une personne de choisir entre ROUGE, VERT et JAUNE ce qui se passe en interne. Qu'est-ce qui fait qu'une personne choisit ROUGE ou JAUNE ou VERT?
Une pensée initiale va dans l'esprit de la personne qui décide de son choix, il peut s'agir de la couleur préférée, de la couleur chanceuse, etc. En d'autres termes, un déclencheur initial que nous appelons RANDOM comme SEED. Ce SEED est le point de départ, le déclencheur qui l'incite à sélectionner la valeur RANDOM.
Maintenant, si un SEED est facile à deviner, ce type de nombres aléatoires est appelé PSEUDO et lorsqu'une graine est difficile à deviner, ces nombres aléatoires sont appelés nombres aléatoires SECURED .
Par exemple, une personne choisit sa couleur en fonction de la météo et de la combinaison sonore, alors il serait difficile de deviner la graine initiale.
Permettez-moi maintenant de faire une déclaration importante: -
* La classe "Random" génère uniquement un nombre aléatoire PSEUDO et pour générer un nombre aléatoire SECURE, nous devons utiliser la classe "RNGCryptoServiceProvider".
La classe aléatoire prend des valeurs de départ de votre horloge CPU, ce qui est très prévisible. Donc, en d'autres termes, la classe RANDOM de C # génère des nombres pseudo-aléatoires, voici le code pour le même.
** Remarque: ** .NET Core 2.0.0+
utilise une graine différente sur le constructeur sans paramètre: au lieu de l'horloge CPU qu'il utilise Guid.NewGuid().GetHashCode()
.
var random = new Random();
int randomnumber = random.Next()
Alors que la RNGCryptoServiceProvider
classe utilise l'entropie du système d'exploitation pour générer des graines. L'entropie du système d'exploitation est une valeur aléatoire qui est générée à l'aide du son, des clics de souris et des synchronisations du clavier, de la température thermique, etc. Ci-dessous, le code correspondant.
using (RNGCryptoServiceProvider rg = new RNGCryptoServiceProvider())
{
byte[] rno = new byte[5];
rg.GetBytes(rno);
int randomvalue = BitConverter.ToInt32(rno, 0);
}
Pour comprendre l'entropie du système d'exploitation, consultez cette vidéo de 14h30 https://www.youtube.com/watch?v=tCYxc-2-3fY où la logique de l'entropie du système d'exploitation est expliquée. Donc, en termes simples, RNG Crypto génère des nombres aléatoires SÉCURISÉS.
RandomNumberGenerator.Create()
au lieu d'appeler le constructeur de RNGCryptoServiceProvider
car il n'est pas disponible sur toutes les plateformes.
Chaque fois que vous faites un nouveau Random (), il est initialisé. Cela signifie que dans une boucle serrée, vous obtenez souvent la même valeur. Vous devez conserver une seule instance aléatoire et continuer à utiliser Next sur la même instance.
//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
objet. Dans les deux cas, j'ai obtenu le même nombre aléatoire. Avec l'approche de Pankaj, cela ne s'est pas produit. C'est peut-être aléatoire , mais j'en doute maintenant. Je demande le nombre aléatoire dans la même seconde à partir de différents threads.
Méfiez-vous qui new Random()
est semé sur l'horodatage actuel.
Si vous souhaitez générer un seul numéro, vous pouvez utiliser:
new Random().Next( int.MinValue, int.MaxValue )
Pour plus d'informations, consultez la classe Random , mais veuillez noter:
Cependant, parce que l'horloge a une résolution finie, l'utilisation du constructeur sans paramètre pour créer différents objets aléatoires en succession étroite crée des générateurs de nombres aléatoires qui produisent des séquences identiques de nombres aléatoires
N'utilisez donc pas ce code pour générer une série de nombres aléatoires.
new Random()
en boucle est un point important.
Je voulais ajouter une version cryptographiquement sécurisée:
Classe RNGCryptoServiceProvider ( MSDN ou dotnetperls )
Il implémente IDisposable.
using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider())
{
byte[] randomNumber = new byte[4];//4 for int32
rng.GetBytes(randomNumber);
int value = BitConverter.ToInt32(randomNumber, 0);
}
Vous pouvez utiliser la méthode StaticRandom de Jon Skeet dans la bibliothèque de classes MiscUtil qu'il a construite pour un nombre pseudo-aléatoire.
using MiscUtil;
...
for (int i = 0; i < 100;
Console.WriteLine(StaticRandom.Next());
J'ai essayé toutes ces solutions à l'exception de la réponse COBOL ... lol
Aucune de ces solutions n'était assez bonne. J'avais besoin de randoms dans une boucle rapide pour int et j'obtenais des tonnes de valeurs en double même dans des plages très larges. Après avoir choisi des résultats aléatoires beaucoup trop longtemps, j'ai décidé de m'attaquer définitivement à ce problème une fois pour toutes.
Tout tourne autour de la graine.
Je crée un entier aléatoire en analysant les non-chiffres de Guid, puis je l'utilise pour instancier ma 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);
}
Mise à jour : l'amorçage n'est pas nécessaire si vous instanciez une fois la classe Random. Il serait donc préférable de créer une classe statique et d'appeler une méthode hors de cela.
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);
}
}
Ensuite, vous pouvez utiliser la classe statique comme ça ..
for(var i = 0; i < 1000; i++)
{
int randomNumber = IntUtil.Random(1,100);
Console.WriteLine(randomNumber);
}
J'avoue que j'aime mieux cette approche.
Les nombres générés par la Random
classe intégrée (System.Random) génèrent des nombres pseudo aléatoires.
Si vous voulez de vrais nombres aléatoires, le plus proche que nous pouvons obtenir est un "générateur pseudo aléatoire sécurisé" qui peut être généré en utilisant les classes cryptographiques en C # telles que RNGCryptoServiceProvider
.
Même ainsi, si vous avez toujours besoin de vrais nombres aléatoires, vous devrez utiliser une source externe telle que des appareils représentant la désintégration radioactive comme source pour un générateur de nombres aléatoires. Puisque, par définition, tout nombre généré par des moyens purement algorithmiques ne peut pas être vraiment aléatoire.
créer un objet aléatoire
Random rand = new Random();
et l'utiliser
int randomNumber = rand.Next(min, max);
vous n'avez pas besoin d'initialiser new Random()
chaque fois que vous avez besoin d'un nombre aléatoire, d'initier un aléatoire puis de l'utiliser autant de fois que nécessaire dans une boucle ou autre
new Random()
utilise les ticks actuels comme graine. Lorsque vous instanciez plusieurs instances dans la même milliseconde (au lieu de cocher), vous obtiendrez la même valeur retournée.
Réponse modifiée d' ici .
Si vous avez accès à un processeur compatible Intel Secure Key, vous pouvez générer de vrais nombres et chaînes aléatoires à l'aide de ces bibliothèques: https://github.com/JebteK/RdRand et https://www.rdrand.com/
Téléchargez simplement la dernière version à partir d' ici , incluez Jebtek.RdRand et ajoutez une instruction using pour cela. Ensuite, tout ce que vous devez faire est le suivant:
// 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();
Si vous n'avez pas de CPU compatible pour exécuter le code, utilisez simplement les services RESTful sur rdrand.com. Avec la bibliothèque d'encapsulation RdRandom incluse dans votre projet, il vous suffira de le faire (vous recevez 1000 appels gratuits lorsque vous vous inscrivez):
string ret = Randomizer.GenerateKey(<length>, "<key>");
uint ret = Randomizer.GenerateUInt("<key>");
byte[] ret = Randomizer.GenerateBytes(<length>, "<key>");
Bien que ce soit correct:
Random random = new Random();
int randomNumber = random.Next()
Vous voudriez contrôler la limite (nombre minimum et maximum) la plupart du temps. Vous devez donc spécifier où commence et se termine le nombre aléatoire.
La Next()
méthode accepte deux paramètres, min et max.
Donc, si je veux que mon nombre aléatoire soit entre disons 5 et 15, je ferais juste
int randomNumber = random.Next(5, 16)
Ceci est la classe que j'utilise. Fonctionne commeRandomNumber.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);
}
}
Je voulais montrer ce qui se passe lorsqu'un nouveau générateur aléatoire est utilisé à chaque fois. Supposons que vous ayez deux méthodes ou deux classes nécessitant chacune un nombre aléatoire. Et vous les codez naïvement comme:
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; }
}
Pensez-vous que vous obtiendrez deux identifiants différents? NAN
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 solution est de toujours utiliser un seul générateur aléatoire statique. Comme ça:
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
c'est un meilleur appel de toute façon.
Pour une graine aléatoire forte, j'utilise toujours CryptoRNG et 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);
Juste comme une note pour référence future.
Si vous utilisez .NET Core, plusieurs instances aléatoires ne sont pas aussi dangereuses qu'auparavant. Je sais que cette question date de 2010, mais comme cette question est ancienne mais présente un certain attrait, je pense que c'est une bonne chose de documenter le changement.
Vous pouvez vous référer à cette question que j'ai posée il y a quelque temps:
Microsoft a-t-il modifié la valeur par défaut Aléatoire?
Fondamentalement, ils ont changé la valeur par défaut de Environment.TickCount
en Guid.NewGuid().GetHashCode()
, donc si vous créez 2 instances de Random, elle n'affichera pas les mêmes nombres.
Vous pouvez voir les différences de fichier de .NET Framework / .NET Core (2.0.0+) ici: https://github.com/dotnet/coreclr/pull/2192/commits/9f6a0b675e5ac0065a268554de49162c539ff66d
Ce n'est pas aussi sûr que RNGCryptoServiceProvider, mais au moins cela ne vous donnera pas de résultats étranges.
Interop.GetRandomBytes((byte*)&result, sizeof(int));
.
Les nombres calculés par un ordinateur selon un processus déterministe, ne peuvent, par définition, être aléatoires.
Si vous voulez un véritable nombre aléatoire, le caractère aléatoire provient du bruit atmosphérique ou de la désintégration radioactive.
Vous pouvez essayer par exemple RANDOM.ORG (cela réduit les performances)
Random rand = new Random();
int name = rand.Next()
Mettez toutes les valeurs que vous voulez dans les deuxièmes parenthèses assurez-vous d'avoir défini un nom en écrivant prop et double tab pour générer le code
Si vous voulez qu'un CSRNG génère des nombres aléatoires entre un min et un max, c'est pour vous. Il initialisera les Random
classes avec des graines aléatoires sécurisées.
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);
}
}
Désolé, OP nécessite en effet une int
valeur aléatoire , mais dans le simple but de partager des connaissances si vous voulez une BigInteger
valeur aléatoire , vous pouvez utiliser la déclaration suivante:
BigInteger randomVal = BigInteger.Abs(BigInteger.Parse(Guid.NewGuid().ToString().Replace("-",""), NumberStyles.AllowHexSpecifier));
Je suppose que vous voulez un générateur de nombres aléatoires uniformément distribué comme ci-dessous. Le nombre aléatoire dans la plupart des langages de programmation, y compris C # et C ++, n'est pas mélangé correctement avant de les utiliser. Cela signifie que vous obtiendrez le même nombre encore et encore, ce qui n'est pas vraiment aléatoire. Pour éviter de tirer le même nombre encore et encore, vous avez besoin d'une graine. En règle générale, les ticks dans le temps conviennent à cette tâche. N'oubliez pas que vous obtiendrez le même nombre encore et encore si vous utilisez la même graine à chaque fois. Essayez donc d'utiliser toujours des semences variées. Le temps est une bonne source de semences car elles changent toujours.
int GetRandomNumber(int min, int max)
{
Random rand = new Random((int)DateTime.Now.Ticks);
return rand.Next(min, max);
}
si vous recherchez un générateur de nombres aléatoires pour une distribution normale, vous pouvez utiliser une transformation Box-Muller. Vérifiez la réponse de yoyoyoyosef dans Question variable gaussienne aléatoire. Puisque vous voulez un entier, vous devez convertir une valeur double en entier à la fin.
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)
Le moyen le plus simple est probablement juste Random.range(1, 3)
Cela générerait un nombre compris entre 1 et 2.
Vous pouvez essayer avec une valeur de départ aléatoire en utilisant ci-dessous:
var rnd = new Random(11111111); //note: seed value is 11111111
string randomDigits = rnd.Next();
var requestNumber = $"SD-{randomDigits}";
Pourquoi ne pas utiliser int randomNumber = Random.Range(start_range, end_range)
?
Utiliser une instance de Random à plusieurs reprises
// 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);
}
Cet article examine les raisons pour lesquelles le caractère aléatoire cause tant de problèmes et comment les résoudre. http://csharpindepth.com/Articles/Chapter12/Random.aspx
Random
n'est pas une classe thread-safe. Si vous créez une seule instance, vous devez restreindre l'accès à celle-ci derrière un mécanisme de verrouillage.
Essayez ces étapes simples pour créer des nombres aléatoires:
Créer une fonction:
private int randomnumber(int min, int max)
{
Random rnum = new Random();
return rnum.Next(min, max);
}
Utilisez la fonction ci-dessus à un endroit où vous souhaitez utiliser des nombres aléatoires. Supposons que vous souhaitiez l'utiliser dans une zone de texte.
textBox1.Text = randomnumber(0, 999).ToString();
0 est min et 999 est max. Vous pouvez modifier les valeurs comme vous le souhaitez.
J'ai toujours des méthodes qui génèrent des nombres aléatoires qui aident à diverses fins. J'espère que cela peut aussi vous aider:
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();
}
}
Rapide et facile pour en ligne, utilisez le code ci-dessous:
new Random().Next(min, max);
// for example unique name
strName += "_" + new Random().Next(100, 999);