843 Stimmen

Zufallszahlengenerator erzeugt nur eine Zufallszahl

Ich habe die folgende Funktion:

//Function to get random number
public static int RandomNumber(int min, int max)
{
    Random random = new Random();
    return random.Next(min, max);
}

Wie ich es nenne:

byte[] mac = new byte[6];
for (int x = 0; x < 6; ++x)
    mac[x] = (byte)(Misc.RandomNumber((int)0xFFFF, (int)0xFFFFFF) % 256);

Wenn ich diese Schleife mit dem Debugger während der Laufzeit durchlaufe, erhalte ich andere Werte (was ich ja auch will). Wenn ich jedoch zwei Zeilen unterhalb dieses Codes einen Haltepunkt setze, werden alle Mitglieder der mac Array haben den gleichen Wert.

Warum ist das so?

27 Stimmen

Mit new Random().Next((int)0xFFFF, (int)0xFFFFFF) % 256); ergibt keine besseren "Zufallszahlen" als .Next(0, 256)

2 Stimmen

Sie finden vielleicht dieses NuGet-Paket hilfreich. Es bietet eine statische Rand.Next(int, int) Methode, die einen statischen Zugriff auf Zufallswerte ermöglicht, ohne Sperren oder das Problem der Wiederverwendung von Seeds zu verursachen

19voto

sabiland Punkte 2406

1) Wie Marc Gravell sagte, versuchen Sie, EINEN Zufallsgenerator zu verwenden. Es ist immer gut, dies dem Konstruktor hinzuzufügen: System.Environment.TickCount.

2) Ein Tipp. Nehmen wir an, Sie wollen 100 Objekte erstellen und nehmen an, dass jedes von ihnen seinen eigenen Zufallsgenerator haben soll (praktisch, wenn Sie LOTZEN von Zufallszahlen in einer sehr kurzen Zeitspanne berechnen müssen). Wenn Sie das in einer Schleife machen würden (Erzeugung von 100 Objekten), könnten Sie das so machen (um die vollständige Zufälligkeit zu gewährleisten):

int inMyRandSeed;

for(int i=0;i<100;i++)
{
   inMyRandSeed = System.Environment.TickCount + i;
   .
   .
   .
   myNewObject = new MyNewObject(inMyRandSeed);  
   .
   .
   .
}

// Usage: Random m_rndGen = new Random(inMyRandSeed);

Zum Wohl.

4 Stimmen

Ich würde System.Environment.TickCount aus der Schleife herausnehmen. Wenn es über tickt, während Sie iterieren, dann haben Sie zwei Elemente, die auf den gleichen Seed initialisiert. Eine andere Möglichkeit wäre, den Tickcount und i anders zu kombinieren (z.B. System.Environment.TickCount<<8 + i)

0 Stimmen

Wenn ich das richtig verstehe: meinen Sie, es könnte passieren, dass "System.Environment.TickCount + i" den GLEICHEN Wert ergibt?

0 Stimmen

EDIT: Natürlich, keine Notwendigkeit, TickCount innerhalb der Schleife haben. Mein Fehler :).

11voto

Joma Punkte 2432

Jedes Mal, wenn Sie die

Random random = new Random (15);

Es spielt keine Rolle, ob Sie es millionenfach ausführen, Sie werden immer denselben Samen verwenden.

Wenn Sie

Random random = new Random ();

Sie erhalten eine andere Zufallszahlenfolge. Wenn ein Hacker den Seed errät und Ihr Algorithmus mit der Sicherheit Ihres Systems zusammenhängt, ist Ihr Algorithmus gebrochen. I Sie führen mult. In diesem Konstruktor wird der Seed durch die Systemuhr festgelegt, und wenn mehrere Instanzen in einer sehr kurzen Zeitspanne (Millisekunden) erstellt werden, ist es möglich, dass sie denselben Seed haben.

Wenn Sie sichere Zufallszahlen benötigen, müssen Sie die Klasse

System.Security.Cryptography.RNGCryptoServiceProvider

public static int Next(int min, int max)
{
    if(min >= max)
    {
        throw new ArgumentException("Min value is greater or equals than Max value.");
    }
    byte[] intBytes = new byte[4];
    using(RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider())
    {
        rng.GetNonZeroBytes(intBytes);
    }
    return  min +  Math.Abs(BitConverter.ToInt32(intBytes, 0)) % (max - min + 1);
}

Verwendung:

int randomNumber = Next(1,100);

3 Stimmen

It does not matter if you execute it millions of times, you will always use the same seed. Das stimmt nicht, es sei denn, Sie geben das Saatgut selbst an.

0 Stimmen

Repariert. Danke Genau wie du sagst, LarsTech, wenn immer derselbe Seed angegeben wird, wird auch immer dieselbe Folge von Zufallszahlen erzeugt. In meiner Antwort beziehe ich mich auf den Konstruktor mit Parametern, wenn man immer den gleichen Seed verwendet. Die Klasse Random erzeugt nur Pseudozufallszahlen. Wenn jemand herausfindet, welchen Seed Sie in Ihrem Algorithmus verwendet haben, kann dies die Sicherheit oder Zufälligkeit Ihres Algorithmus gefährden. Mit der Klasse RNGCryptoServiceProvider können Sie sicher Zufallszahlen verwenden. Ich habe das bereits korrigiert, vielen Dank für die Korrektur.

0 Stimmen

Es ist übertrieben, den Begriff new RNGCryptoServiceProvider() an jedem Next . Erklären Sie stattdessen private static RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); Dann entfernen Sie die using Wrapper; rufen Sie einfach rng.GetNonZeroBytes(intBytes); auf diese Statik.

0voto

Sie können einen Code wie diesen verwenden:

public static class ThreadSafeRandom
{
    private static readonly Random _global = new Random();
    private static readonly ThreadLocal<Random> _local = new ThreadLocal<Random>(() =>
    {
        int seed;
        lock (_global)
        {
            seed = _global.Next();
        }
        return new Random(seed);
    });

    public static Random Instance => _local.Value;
}

Dieser Code kann unverändert oder über das NuGet-Paket verwendet werden ThreadSafeRandomizer .

-1voto

SZL Punkte 639

Ich benutze dies:

int randomNumber = int.Parse(Guid.NewGuid().ToString().FirstOrDefault(Char.IsDigit).ToString().Replace("\0", "0"));

Leistung: Generierung von 1 Million Zufallszahlen auf meinem PC: 711 ms.

Wenn die Guid keine Zahl enthält (ich weiß nicht, ob das möglich ist oder nicht), wird 0 als Ergebnis verwendet.

-2voto

Paolo Barone Punkte 69

Ich habe das Problem durch die Verwendung der Funktion Rnd() gelöst:

Function RollD6() As UInteger
        RollD6 = (Math.Floor(6 * Rnd())) + 1
        Return RollD6
End Function

Wenn das Formular geladen wird, verwende ich die Methode Randomize(), um sicherzustellen, dass ich nicht immer dieselbe Folge von Zufallszahlen erhalte.

2 Stimmen

Diese Frage bezieht sich auf C#, nicht auf Visual Basic.NET. (Obwohl beides .NET-Sprachen sind, und obwohl es möglich, aber nicht so trivial ist, von C# aus auf VB-Funktionen zuzugreifen).

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X