Benutzer mit den meisten Antworten
Problem mit Random: Immer derselbe Wert, wenn ich Random in einer Klasse aufrufe

Frage
-
Hallo,
bei folgendem Code wird das Array stars mit 100 identischen Zufallszahlen gefüllt:
using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace ConsoleApp1 { class Star { public int vx; Random r = new Random(); public Star() { vx = r.Next(); } } class Program { static void Main(string[] args) { Star[] stars = new Star[100]; for (int i = 0; i < stars.Length; i++) { stars[i] = new Star(); // Thread.Sleep(10); } for (int i = 0; i < stars.Length; i++) { Console.WriteLine(stars[i].vx); } Console.ReadKey(); } } }
In der Ausgabeschleife sind alle Werte gleich. Ich habe schon einiges getestet:
- Wenn ich die Zufallszahlen in einer eigenen Methode zuweise, bleibt das Problem bestehen.
- Wenn ich die Zufallszahlen in Main erzeuge und als Parameter übergebe, ist alles ok.
- Wenn ich nach vx = r.Next() eine Thread.Sleep(10)-Anweisung einfüge, erhalte ich meistens eine neue Zufallszahl, oft aber 2x dieselbe und erst dann eine neue. Bei Thread.Sleep(20) sind die Zufallszahlen dann ok.
Getestet habe ich mit Visual Studio 2013 und Visual Studio 2017RC.
Ich verstehe das nicht. Weiß jemand, woran das liegt?
- Bearbeitet H St Montag, 27. Februar 2017 23:51
Antworten
-
Hallo,
Siehe Random-Konstruktor: (): "Initialisiert eine neue Instanz der Random -Klasse unter Verwendung eines zeitabhängigen Standardstartwerts"
Erstellst Du also die Random Klassen alle zu einem Zeitpunkt, was Du ohne Sleep defacto tust, erhälst Du hier immer die gleichen Zufallszahlen. Verwende besser nur eine einzige Random Instanz im Programm-Main-Teil und weise den Zufallswert bei der Star Klasseninstanzierung von extern zu.
Olaf Helper
[ Blog] [ Xing] [ MVP]- Als Antwort vorgeschlagen Florian Haupt Dienstag, 28. Februar 2017 07:49
- Als Antwort markiert Dimitar DenkovMicrosoft contingent staff, Administrator Dienstag, 7. März 2017 17:40
-
Hallo,
das Problem ist, das die Random-Klasse auch nur auf einem Algorithmus basiert, der eine scheinbar zufällige Zahlenfolge ausgibt. Entscheident ist dabei der Start-Wert, der dem Konstruktor übergeben werden kann. Wenn du keinen Wert übergibst, wird die aktuelle Tick-Zahl benutzt um einen möglichst nicht wiederholenden Startwert zu erhalten.
Wenn du das allerdings sehr oft direkt hintereinander machst, erhältst du trotzdem immer wieder den selben Wert als erstes, da der Startwert immer gleich bleibt.
Als Abhilfe musst du nach Möglichkeit nur eine Instanz der Klasse benutzen, indem du das Feld statisch machst:
static Random r = new Random();
Dadurch greifen dann alle Instanzen der Star-Klasse auf die selbe Random-Instanz zu und die Klasse wird nur einmal initialisiert. Dadurch erhältst du zufällig aussehende Zahlen.
Solltest du mehrere Klassen haben, die Zufallszahlen generieren, dann kannst du dir diese Statische-Random-Instanz auch auslagern und so eine Instanz über mehrere Klassen hinweg teilen.
Viele Grüße, Tom Lambert - MVP, MCC und MSP
Wozu Antworten markieren und Posts bewerten? Klicke hier
Nützliche Links: .NET Quellcode | C#/VB.NET Konverter | GitHub Forum Samples | Account bestätigen (Verify Your Account)
Ich: Webseite | Facebook | Twitter | Code Snippets | GitHub
- Bearbeitet Tom Lambert (Koopakiller)Moderator Dienstag, 28. Februar 2017 04:58
- Als Antwort vorgeschlagen Florian Haupt Dienstag, 28. Februar 2017 07:49
- Als Antwort markiert Dimitar DenkovMicrosoft contingent staff, Administrator Dienstag, 7. März 2017 17:40
Alle Antworten
-
Hallo,
Siehe Random-Konstruktor: (): "Initialisiert eine neue Instanz der Random -Klasse unter Verwendung eines zeitabhängigen Standardstartwerts"
Erstellst Du also die Random Klassen alle zu einem Zeitpunkt, was Du ohne Sleep defacto tust, erhälst Du hier immer die gleichen Zufallszahlen. Verwende besser nur eine einzige Random Instanz im Programm-Main-Teil und weise den Zufallswert bei der Star Klasseninstanzierung von extern zu.
Olaf Helper
[ Blog] [ Xing] [ MVP]- Als Antwort vorgeschlagen Florian Haupt Dienstag, 28. Februar 2017 07:49
- Als Antwort markiert Dimitar DenkovMicrosoft contingent staff, Administrator Dienstag, 7. März 2017 17:40
-
Hallo,
das Problem ist, das die Random-Klasse auch nur auf einem Algorithmus basiert, der eine scheinbar zufällige Zahlenfolge ausgibt. Entscheident ist dabei der Start-Wert, der dem Konstruktor übergeben werden kann. Wenn du keinen Wert übergibst, wird die aktuelle Tick-Zahl benutzt um einen möglichst nicht wiederholenden Startwert zu erhalten.
Wenn du das allerdings sehr oft direkt hintereinander machst, erhältst du trotzdem immer wieder den selben Wert als erstes, da der Startwert immer gleich bleibt.
Als Abhilfe musst du nach Möglichkeit nur eine Instanz der Klasse benutzen, indem du das Feld statisch machst:
static Random r = new Random();
Dadurch greifen dann alle Instanzen der Star-Klasse auf die selbe Random-Instanz zu und die Klasse wird nur einmal initialisiert. Dadurch erhältst du zufällig aussehende Zahlen.
Solltest du mehrere Klassen haben, die Zufallszahlen generieren, dann kannst du dir diese Statische-Random-Instanz auch auslagern und so eine Instanz über mehrere Klassen hinweg teilen.
Viele Grüße, Tom Lambert - MVP, MCC und MSP
Wozu Antworten markieren und Posts bewerten? Klicke hier
Nützliche Links: .NET Quellcode | C#/VB.NET Konverter | GitHub Forum Samples | Account bestätigen (Verify Your Account)
Ich: Webseite | Facebook | Twitter | Code Snippets | GitHub
- Bearbeitet Tom Lambert (Koopakiller)Moderator Dienstag, 28. Februar 2017 04:58
- Als Antwort vorgeschlagen Florian Haupt Dienstag, 28. Februar 2017 07:49
- Als Antwort markiert Dimitar DenkovMicrosoft contingent staff, Administrator Dienstag, 7. März 2017 17:40