Antworten:
Die Random
Klasse wird verwendet, um Zufallszahlen zu erstellen. (Das ist natürlich pseudozufällig.)
Beispiel:
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
Wenn Sie mehr als eine Zufallszahl erstellen möchten, sollten Sie die Random
Instanz behalten und wiederverwenden. Wenn Sie neue Instanzen zu nahe an der Zeit erstellen, erzeugen sie dieselbe Reihe von Zufallszahlen, wie der Zufallsgenerator aus der Systemuhr ausgesät wird.
rnd
wie static
und / oder es nur einmal festgelegt , wenn der Code initialisiert wird .
Random
...
Random
um Ihre Zufälligkeit robuster zu machen: ericlippert.com/2019/02/04/fixing-random-part-2 und codeblog.jonskeet.uk/2009/11/04/revisiting Zufälligkeit .
Die Frage sieht sehr einfach aus, aber die Antwort ist etwas kompliziert. Wenn Sie sehen, hat fast jeder vorgeschlagen, die Random-Klasse zu verwenden, und einige haben vorgeschlagen, die RNG-Krypto-Klasse zu verwenden. Aber wann soll man was wählen?
Dazu müssen wir zuerst den Begriff RANDOMNESS und die dahinter stehende Philosophie verstehen.
Ich möchte Sie ermutigen, dieses Video, das sich eingehend mit der Philosophie von RANDOMNESS befasst, mit C # https://www.youtube.com/watch?v=tCYxc-2-3fY anzusehen
Lassen Sie uns als erstes die Philosophie der Zufälligkeit verstehen. Wenn wir einer Person sagen, dass sie zwischen ROT, GRÜN und GELB wählen soll, was intern passiert. Was bringt eine Person dazu, ROT oder GELB oder GRÜN zu wählen?
Ein erster Gedanke geht in den Kopf des Menschen, der über seine Wahl entscheidet. Es kann Lieblingsfarbe, Glücksfarbe und so weiter sein. Mit anderen Worten, ein anfänglicher Auslöser, den wir in RANDOM als SEED bezeichnen. Dieser SEED ist der Anfangspunkt, der Auslöser, der ihn dazu veranlasst, den RANDOM-Wert auszuwählen.
Wenn ein SEED leicht zu erraten ist, werden diese Zufallszahlen als PSEUDO bezeichnet, und wenn ein Samen schwer zu erraten ist, werden diese Zufallszahlen als SECURED- Zufallszahlen bezeichnet.
Zum Beispiel wählt eine Person die Farbe in Abhängigkeit von Wetter und Klangkombination, dann wäre es schwierig, den anfänglichen Samen zu erraten.
Lassen Sie mich jetzt eine wichtige Aussage machen:
* Die Klasse "Random" generiert nur eine PSEUDO-Zufallszahl. Um eine sichere Zufallszahl zu generieren, müssen Sie die Klasse "RNGCryptoServiceProvider" verwenden.
Die zufällige Klasse nimmt Startwerte von Ihrem CPU-Takt, was sehr vorhersehbar ist. Mit anderen Worten, die RANDOM-Klasse von C # erzeugt Pseudozufallszahlen. Nachfolgend finden Sie den Code für dieselbe.
** Hinweis: ** .NET Core 2.0.0+
verwendet einen anderen Startwert für den parameterlosen Konstruktor: Anstelle des verwendeten CPU-Takts Guid.NewGuid().GetHashCode()
.
var random = new Random();
int randomnumber = random.Next()
Während die RNGCryptoServiceProvider
Klasse OS-Entropie verwendet, um Seeds zu generieren. Die OS-Entropie ist ein zufälliger Wert, der mithilfe von Sound, Mausklick und Tastatur-Timings, thermischer Temperatur usw. generiert wird. Nachfolgend finden Sie den Code für denselben Wert.
using (RNGCryptoServiceProvider rg = new RNGCryptoServiceProvider())
{
byte[] rno = new byte[5];
rg.GetBytes(rno);
int randomvalue = BitConverter.ToInt32(rno, 0);
}
Um die OS-Entropie zu verstehen, sehen Sie sich dieses Video ab 14:30 https://www.youtube.com/watch?v=tCYxc-2-3fY an, in dem die Logik der OS-Entropie erklärt wird. Wenn Sie also einfache Worte eingeben, generiert RNG Crypto SICHERE Zufallszahlen.
RandomNumberGenerator.Create()
, den Konstruktor von zu verwenden, anstatt ihn aufzurufen, RNGCryptoServiceProvider
da er nicht auf allen Plattformen verfügbar ist.
Jedes Mal, wenn Sie ein neues Random () ausführen, wird es initialisiert. Dies bedeutet, dass Sie in einer engen Schleife oft den gleichen Wert erhalten. Sie sollten eine einzelne Zufallsinstanz beibehalten und Next auf derselben Instanz verwenden.
//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
Objekt zu speichern . In beiden Fällen habe ich die gleiche Zufallszahl bekommen. Mit der Annäherung von Pankaj ist es nicht passiert. Vielleicht ist das zufällig , aber ich bezweifle es jetzt. Ich frage in derselben Sekunde nach der Zufallszahl aus verschiedenen Threads.
Beachten Sie, dass dies new Random()
auf dem aktuellen Zeitstempel festgelegt ist.
Wenn Sie nur eine Zahl generieren möchten, können Sie Folgendes verwenden:
new Random().Next( int.MinValue, int.MaxValue )
Weitere Informationen finden Sie in der Random- Klasse. Beachten Sie jedoch Folgendes:
Da die Uhr jedoch eine endliche Auflösung hat, werden durch die Verwendung des parameterlosen Konstruktors zum Erstellen verschiedener Zufallsobjekte in enger Folge Zufallszahlengeneratoren erstellt, die identische Folgen von Zufallszahlen erzeugen
Verwenden Sie diesen Code also nicht, um eine Reihe von Zufallszahlen zu generieren.
new Random()
es ein wichtiger Punkt ist , nicht in einer Schleife zu arbeiten.
Ich wollte eine kryptografisch sichere Version hinzufügen:
RNGCryptoServiceProvider-Klasse ( MSDN oder dotnetperls )
Es implementiert IDisposable.
using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider())
{
byte[] randomNumber = new byte[4];//4 for int32
rng.GetBytes(randomNumber);
int value = BitConverter.ToInt32(randomNumber, 0);
}
Sie können die StaticRandom- Methode von Jon Skeet in der MiscUtil-Klassenbibliothek verwenden, die er für eine Pseudozufallszahl erstellt hat.
using MiscUtil;
...
for (int i = 0; i < 100;
Console.WriteLine(StaticRandom.Next());
Ich habe alle diese Lösungen mit Ausnahme der COBOL-Antwort ausprobiert ... lol
Keine dieser Lösungen war gut genug. Ich brauchte Zufälle in einer schnellen for-Schleife und bekam sogar in sehr weiten Bereichen Tonnen von doppelten Werten. Nachdem ich mich viel zu lange mit zufälligen Ergebnissen zufrieden gegeben hatte, beschloss ich, dieses Problem endlich ein für alle Mal anzugehen.
Es geht nur um den Samen.
Ich erstelle eine zufällige Ganzzahl, indem ich die Nicht-Ziffern aus Guid analysiere, und verwende diese dann, um meine Zufallsklasse zu instanziieren.
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);
}
Update : Seeding ist nicht erforderlich, wenn Sie die Random-Klasse einmal instanziieren. Es ist also am besten, eine statische Klasse zu erstellen und eine Methode daraus aufzurufen.
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);
}
}
Dann können Sie die statische Klasse wie folgt verwenden.
for(var i = 0; i < 1000; i++)
{
int randomNumber = IntUtil.Random(1,100);
Console.WriteLine(randomNumber);
}
Ich gebe zu, dass mir dieser Ansatz besser gefällt.
Die von der eingebauten Random
Klasse (System.Random) generierten Zahlen erzeugen Pseudozufallszahlen.
Wenn Sie echte Zufallszahlen wünschen, ist der "sichere Pseudozufallsgenerator" der nächstgelegene, der mithilfe der kryptografischen Klassen in C # wie z RNGCryptoServiceProvider
.
Wenn Sie dennoch echte Zufallszahlen benötigen, müssen Sie eine externe Quelle verwenden, z. B. Geräte, die den radioaktiven Zerfall berücksichtigen, als Keim für einen Zufallszahlengenerator. Da per Definition jede mit rein algorithmischen Mitteln erzeugte Zahl nicht wirklich zufällig sein kann.
Erstellen Sie ein zufälliges Objekt
Random rand = new Random();
und benutze es
int randomNumber = rand.Next(min, max);
Sie müssen nicht new Random()
jedes Mal initialisieren, wenn Sie eine Zufallszahl benötigen. Initiieren Sie eine Zufallszahl und verwenden Sie sie dann so oft, wie Sie in einer Schleife oder was auch immer benötigen
new Random()
verwendet die aktuellen Zecken als Startwert. Wenn Sie mehrere Instanzen innerhalb derselben Millisekunde instanziieren (im Gegensatz zu tick), wird derselbe Wert zurückgegeben.
Geänderte Antwort von hier .
Wenn Sie Zugriff auf eine Intel Secure Key-kompatible CPU haben, können Sie mithilfe dieser Bibliotheken echte Zufallszahlen und Zeichenfolgen generieren: https://github.com/JebteK/RdRand und https://www.rdrand.com/
Laden Sie einfach die neueste Version von hier herunter, fügen Sie Jebtek.RdRand hinzu und fügen Sie eine using-Anweisung dafür hinzu. Dann müssen Sie nur noch Folgendes tun:
// 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();
Wenn Sie keine kompatible CPU haben, auf der der Code ausgeführt werden kann, verwenden Sie einfach die RESTful-Dienste unter rdrand.com. Mit der in Ihrem Projekt enthaltenen RdRandom-Wrapper-Bibliothek müssten Sie dies nur tun (Sie erhalten 1000 kostenlose Anrufe, wenn Sie sich anmelden):
string ret = Randomizer.GenerateKey(<length>, "<key>");
uint ret = Randomizer.GenerateUInt("<key>");
byte[] ret = Randomizer.GenerateBytes(<length>, "<key>");
Während das in Ordnung ist:
Random random = new Random();
int randomNumber = random.Next()
Sie möchten das Limit (minimale und maximale Anzahl) die meiste Zeit steuern. Sie müssen also angeben, wo die Zufallszahl beginnt und endet.
Die Next()
Methode akzeptiert zwei Parameter, min und max.
Wenn ich also möchte, dass meine Zufallszahl zwischen 5 und 15 liegt, würde ich es einfach tun
int randomNumber = random.Next(5, 16)
Dies ist die Klasse, die ich benutze. Funktioniert wieRandomNumber.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);
}
}
Ich wollte zeigen, was passiert, wenn jedes Mal ein neuer Zufallsgenerator verwendet wird. Angenommen, Sie haben zwei Methoden oder zwei Klassen, für die jeweils eine Zufallszahl erforderlich ist. Und naiv codieren Sie sie wie folgt:
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; }
}
Glaubst du, du bekommst zwei verschiedene IDs? NEE
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
}
}
Die Lösung besteht darin, immer einen einzigen statischen Zufallsgenerator zu verwenden. So was:
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
ist dies sowieso ein besserer Anruf.
Für starke zufällige Samen verwende ich immer CryptoRNG und nicht 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);
Nur als Hinweis für zukünftige Referenz.
Wenn Sie .NET Core verwenden, sind mehrere zufällige Instanzen nicht mehr so gefährlich wie zuvor. Ich bin mir bewusst, dass diese Frage aus dem Jahr 2010 stammt, aber da diese Frage alt ist, aber eine gewisse Anziehungskraft hat, halte ich es für eine gute Sache, die Änderung zu dokumentieren.
Sie können sich auf diese Frage beziehen, die ich vor einiger Zeit gestellt habe:
Hat Microsoft den zufälligen Standard-Startwert geändert?
Grundsätzlich haben sie den Standard-Startwert von Environment.TickCount
in geändert. Guid.NewGuid().GetHashCode()
Wenn Sie also zwei Instanzen von Random erstellen, werden nicht dieselben Zahlen angezeigt.
Sie können die Dateiunterschiede zu .NET Framework / .NET Core (2.0.0+) hier sehen: https://github.com/dotnet/coreclr/pull/2192/commits/9f6a0b675e5ac0065a268554de49162c539ff66d
Es ist nicht so sicher wie RNGCryptoServiceProvider, aber es liefert zumindest keine seltsamen Ergebnisse.
Interop.GetRandomBytes((byte*)&result, sizeof(int));
.
Zahlen, die von einem Computer durch einen deterministischen Prozess berechnet werden, können per Definition nicht zufällig sein.
Wenn Sie echte Zufallszahlen wollen, kommt die Zufälligkeit von atmosphärischem Rauschen oder radioaktivem Zerfall.
Sie können zum Beispiel RANDOM.ORG ausprobieren (es reduziert die Leistung)
Random rand = new Random();
int name = rand.Next()
Fügen Sie die gewünschten Werte in die zweiten Klammern ein. Stellen Sie sicher, dass Sie einen Namen festgelegt haben, indem Sie prop und double tab schreiben, um den Code zu generieren
Wenn Sie möchten, dass ein CSRNG Zufallszahlen zwischen min und max generiert, ist dies das Richtige für Sie. Es werden Random
Klassen mit sicheren zufälligen Startwerten initialisiert .
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);
}
}
Entschuldigung, OP erfordert zwar einen zufälligen int
Wert, aber für den einfachen Zweck, Wissen zu teilen, wenn Sie einen zufälligen BigInteger
Wert möchten , können Sie die folgende Anweisung verwenden:
BigInteger randomVal = BigInteger.Abs(BigInteger.Parse(Guid.NewGuid().ToString().Replace("-",""), NumberStyles.AllowHexSpecifier));
Ich gehe davon aus, dass Sie einen gleichmäßig verteilten Zufallszahlengenerator wie unten wollen. Die Zufallszahl in den meisten Programmiersprachen, einschließlich C # und C ++, wird vor der Verwendung nicht richtig gemischt. Dies bedeutet, dass Sie immer wieder dieselbe Nummer erhalten, was nicht wirklich zufällig ist. Um zu vermeiden, dass immer wieder dieselbe Zahl gezogen wird, benötigen Sie einen Samen. In der Regel sind zeitliche Ticks für diese Aufgabe in Ordnung. Denken Sie daran, dass Sie immer wieder dieselbe Nummer erhalten, wenn Sie jedes Mal denselben Samen verwenden. Versuchen Sie also immer, unterschiedliche Samen zu verwenden. Zeit ist eine gute Quelle für Samen, weil sie immer chagen.
int GetRandomNumber(int min, int max)
{
Random rand = new Random((int)DateTime.Now.Ticks);
return rand.Next(min, max);
}
Wenn Sie nach einem Zufallszahlengenerator für die Normalverteilung suchen, können Sie eine Box-Muller-Transformation verwenden. Überprüfen Sie die Antwort von yoyoyoyosef in Random Gaussian Variable Question. Da Sie eine Ganzzahl möchten, müssen Sie am Ende einen doppelten Wert in eine Ganzzahl umwandeln.
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)
Der einfachste Weg ist wahrscheinlich nur Random.range(1, 3)
Dies würde eine Zahl zwischen 1 und 2 erzeugen.
Sie können es mit einem zufälligen Startwert versuchen, indem Sie Folgendes verwenden:
var rnd = new Random(11111111); //note: seed value is 11111111
string randomDigits = rnd.Next();
var requestNumber = $"SD-{randomDigits}";
Warum nicht verwenden int randomNumber = Random.Range(start_range, end_range)
?
Verwenden Sie eine Instanz von Random wiederholt
// 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);
}
In diesem Artikel wird untersucht, warum Zufälligkeit so viele Probleme verursacht und wie sie behoben werden können. http://csharpindepth.com/Articles/Chapter12/Random.aspx
Random
ist keine thread-sichere Klasse. Wenn Sie eine einzelne Instanz erstellen, sollten Sie den Zugriff auf diese Instanz hinter einem Sperrmechanismus einschränken.
Versuchen Sie diese einfachen Schritte, um Zufallszahlen zu erstellen:
Funktion erstellen:
private int randomnumber(int min, int max)
{
Random rnum = new Random();
return rnum.Next(min, max);
}
Verwenden Sie die obige Funktion an einem Ort, an dem Sie Zufallszahlen verwenden möchten. Angenommen, Sie möchten es in einem Textfeld verwenden.
textBox1.Text = randomnumber(0, 999).ToString();
0 ist min und 999 ist max. Sie können die Werte beliebig ändern.
Ich habe immer Methoden, die Zufallszahlen erzeugen, die für verschiedene Zwecke helfen. Ich hoffe das kann dir auch helfen:
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();
}
}
Verwenden Sie für den Inline-Modus schnell und einfach den folgenden Code:
new Random().Next(min, max);
// for example unique name
strName += "_" + new Random().Next(100, 999);