Freitag, 4. Juni 2010

Zufallszahlen erzeugen

Zufällige Parameter spielen, auch wenn man es vielleicht nicht erwartet, doch eine große Rolle beim Entwurf von vielen Programmen. Vor allem bei Spielen sind Zufallswerte unerlässlich.
Ein Computer kann aber keine "wirklichen" Zufallszahlen erzeugen, sondern nur Pseudozufallszahlen. Gute Pseudozufallszahlen sehen zwar statistisch zufällig aus, d.h. jede mögliche Zahl hat in etwa die gleiche Wahrscheinlichkeit, in Wirklichkeit werden sie aber durch einen Algorithmus erzeugt.
Wer Interesse bekommen hat kann gerne woanders suchen, es lohnt sich. Hier wollen wir aber nicht näher auf das theoretische Prinzip eingehen, sondern mit "hartem Code".
In C# ist die Klasse Random für Zufallszahlen zuständig.
Sie kann entweder parameterlos initialisiert werden oder mit einem Seed (eine Zahl, die der Erzeugungsalgorithmus als Startwert nimmt).
Die Funktion Next() ist schließlich die Funktion, die eine Zufallszahl liefert. Sie hat 3 Überladungen, die ich an einem Beispiel zeigen möchte:

Random Rnd = new Random(); // initialisiert die Zufallsklasse
int RndNr1 = Rnd.Next();
int RndNr2 = Rnd.Next(10000);
int RndNr3 = Rnd.Next(0, 2);
Der parameterlose Funktionsaufruf speichert in RndNr1 eine nicht-negative Zufallszahl. Die Zufallszahl kann alle möglichen integer - Werte annehmen.
Wird der Funktion ein Parameter übergeben, ist dieses die ausschließliche obere Grenze. Es werden also nur integer - Werte < der oberen Grenze ausgegeben.
Wird Next() mit 2 Parametern aufgerufen, ist ersterer die einschließliche untere Grenze und zweiterer wieder die ausschließliche obere Grenze, sie wird also nie zurückgegeben.
RndNr3 erhält im obigen Beispiel also entweder 0 oder 1 als Wert.
Die Zufallswerte sahen bei einer Ausführung so aus:
RndNr1 = 304286837
RndNr2 = 9060
RndNr3 = 0

Kommentare:

  1. Antworten
    1. Der Kommentar wurde von einem Blog-Administrator entfernt.

      Löschen
  2. Diese tiefgründige Diskussion hat mein Leben bereichert xD

    AntwortenLöschen
  3. Meine auch !!!!!!!!!

    AntwortenLöschen
  4. Danke, dank den tiefgreifenden Worten habe ich jetzt den Sinn meines Lebens gefunden!!!

    AntwortenLöschen
  5. hmmm...
    ich stimme den vorangegengenen argumenten zu!

    AntwortenLöschen
  6. LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOL

    so unwitzig :)

    AntwortenLöschen
  7. xD nicht schlecht...
    Zur Abwechslung mal was konstruktives: Hat jemand eine Ahnung wie das mit vordefinierten Zufallszeichen geht?

    AntwortenLöschen
  8. Was für vordefinierte Zufallszeichen ?????

    LOL 8)

    AntwortenLöschen
  9. Der Kommentar wurde von einem Blog-Administrator entfernt.

    AntwortenLöschen
  10. Der Kommentar wurde von einem Blog-Administrator entfernt.

    AntwortenLöschen
  11. @Anonym

    Ich beziehe mich auf folgenden Text:
    "Zur Abwechslung mal was konstruktives: Hat jemand eine Ahnung wie das mit vordefinierten Zufallszeichen geht?"

    Wenn du bei der Initialisierung des Random Objekt's immer den gleichen Seed übergibst, erhälst du immer die gleiche Reihenfolge von Zufallszahlen.
    Also (Beispiel):

    Random rand = new Random(1);

    Oder wie hattest du das Gemeint?

    AntwortenLöschen
  12. Hallo,

    generell freue ich mich natürlich über die zahlreichen Kommentare auf dem Blog hier, und ab und zu ein paar nicht zum Thema passende Kommentare sind ja auch ganz lustig.
    Trotzdem möchte ich darum bitten, in den Kommentaren einen gewissen Respekt gegenüber anderen Nutzern einzuhalten. Wegen Nichteinhaltung habe ich oben 2 Kommentare entfernt.
    Danke

    AntwortenLöschen
  13. Und ich schließe mich Postremus an, die Frage oben verstehe ich auch nicht ganz, finde aber Postremus Antwort trotzdem sehr treffend.

    AntwortenLöschen
  14. Eine Bessere Auflistung der einzelnen Fälle würde mir besser gefallen. So als liste und nicht als ein Text Absatz.

    AntwortenLöschen
    Antworten
    1. Okay, danke für den Hinweis. Das stimmt, ich glaube in neueren Posts benutzte ich soetwas häufiger.

      Löschen
  15. Geben Sie einen Kommentar ein...

    AntwortenLöschen
    Antworten
    1. Geben sie ihre Antwort ein...

      Löschen
    2. Antwort als: Anonym

      Löschen
  16. Mal ehrlich, die kurzen Zeilen haben mir geholfen.
    Wie kann ich aber zwei generierte Zahlen vergleichen und Gleichheit ausschliessen?

    private void btnStart_Click(object sender, EventArgs e)
    {

    Random Zufall1 = new Random();
    int zuf1 = Zufall1.Next ();
    int zuf2 = Zufall1.Next (!=zuf1);
    int zuf3 = Zufall1.Next (!=zuf2);
    int zuf4 = Zufall1.Next (!=zuf3);

    dieser klägliche und andere funktionieren nicht!

    Gruss

    AntwortenLöschen
    Antworten
    1. Hi,
      meinst du so etwas?

      Random Zufall1 = new Random();
      int zuf1 = Zufall1.Next();
      int zuf2 = Zufall1.Next();

      while (zuf2 == zuf1)
      {
      zuf2 = Zufall1.Next();
      }

      Löschen
  17. Hat jm ne Antwort darauf warum die erste Zahl immer eine 0 ist?
    Cheers

    AntwortenLöschen
    Antworten
    1. Welche 1. Zahl?
      Du meinst, immer wenn du Zufallszahlen erzeugst, werden die gleichen Zufallszahlen nach Programmstart erzeugt?
      Dürfte eigentlich nicht der Fall sein wenn du Random Rnd = new Random() benutzt, da hierbei ein zeitabhängiger Startwert als "Seed" benutzt wird, sodass jedes Mal andere Zahlen herauskommen.

      Löschen
  18. Gibt es auch eine Klasse für Zufallszahlen die einen nicht zeitabhängigen Startwert haben?

    Hab hier das Problem, das wenn ich zB. eine Statistik über einen Würfelwurf aufstelle ich die If-Schleife 1000 mal zum "gleichen" Zeitenpunkt abläuft und die "zufälligen" Ergebnisse sich meist nur auf 1 oder 2 Werte verteilen.

    grüße

    AntwortenLöschen
  19. Geben sie ein Kommentar ein ...

    --> REPOST

    AntwortenLöschen
  20. public static string Zufallszahlen(Int64 pSchlüsselLänge)
    {
    string Rnd = "";

    ////////////////////////////////////////-----------Zufallszahlen über Mauszeigerposition-------------////////////////////////

    //System.Threading.Thread.Sleep(200);

    //while (Rnd.Length <= pSchlüsselLänge * 8)
    //{
    // int Schlüssel = Convert.ToInt64(Cursor.Position.X);
    // Schlüssel = Schlüssel % 2;
    // System.Threading.Thread.Sleep(10);
    // Rnd += Schlüssel.ToString();
    //}

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    RNGCryptoServiceProvider xy = new RNGCryptoServiceProvider();
    byte[] chiffre = new byte[Convert.ToInt64(pSchlüsselLänge *8)];
    xy.GetBytes(chiffre);

    for (int i = 0; i < pSchlüsselLänge * 8; i++)
    {
    Rnd += Convert.ToInt32(chiffre[i]) % 2;
    }


    return Rnd;
    }

    AntwortenLöschen
    Antworten
    1. gibt noch ganz andere möglichkeiten, aber die beiden sind ganz brauchbar

      Löschen
  21. Wenn verschiedene Random-Klassen zu ähnlichen Zeitpunkten erzeugt werden, werden sie die selbe Abfolge an Zahlen liefern. Wenn das nicht erwünscht ist, kann man folgendes machen:

    Random rnd = new Random(Guid.NewGuid().GetHashCode());

    Was passiert ist, dass ein hochgradig seltener String erzeugt wird (Guid.NewGuid()), der normalerweise für Identifikationszwecke verwendet wird. Nun ist ein String ungeeignet, um die Randomklasse zu initialisieren. Deswegen bildet man den Hash-Code daraus. Der Hash-Code ist ein Versuch, ein Objekt möglichst eindeutig als Integer zu identifizieren. Das Ergebnis ist ein Integer mit Seltenheitswert.

    Auch möglich ist es, irgendwo einmal _eine_ Random-Klasse zu initialisieren, und dann immer von überall auf die zuzugreifen. Das ist aber etwas umständlich...

    AntwortenLöschen
  22. Dieser Kommentar wurde vom Autor entfernt.

    AntwortenLöschen
  23. Hi,
    da hier ja zwischendurch wikrlich brauchbare und konstruktive Antworten dabei sind versuch ich mal mein Glück ;-)

    Und zwar möchte ich einen "zufallsgenerator" für Würfelergebnisse machen. Kurze Erklärung:

    Es sollen, bestenfalls in einer Foms Anwendunug, auf Knopfdruck 4 Zahlenwerte von 1-6 (würfel) erzeugt und zusammengezählt werden, wobei das niedrigste Ergebnis NICHT gezählt wird..
    Bsp.:
    6-5-4(-3)= 6+5+4 = 15

    Und das Ganze dann 6x.. Also ich hab jetzt eine GUI mit 6 Textboxen und 1 Button.
    Kann mir da vielleicht irgendjemand helfen?? Wäre super ;-)
    Danke schonmal

    MfG
    Ben G.

    AntwortenLöschen
    Antworten
    1. Erstmal danke für die interessanten und konstruktiven Antworten hier!

      Dann zur Beantwortung der letzten Frage, folgender Code sollte deine Idee umsetzen:

      Random Rnd = new Random();
      int[] Values = new int[4];
      int Sum;
      for (int i = 0; i < 6; i++)
      {
      Sum = 0;
      for (int j=0;j<4;j++)
      {
      Values[j] = Rnd.Next(1, 7);
      }

      int Min = MinIndex(Values);

      for (int j = 0; j < 4; j++)
      {
      if (j == Min)
      continue;
      Sum += Values[j];
      }
      }

      Wobei die Funktion MinIndex wie folgt definiert ist:

      public int MinIndex(int[] array)
      {
      int MinValue = int.MaxValue;
      int MinPos = 0;
      for (int i = 0; i < array.Length; i++)
      {
      if (array[i] < MinValue)
      {
      MinValue = array[i];
      MinPos = i;
      }
      }
      return MinPos;
      }

      Löschen
  24. Anonymität ftw. Trotzdem Leute.. postet bitte keine unnötigen Kommentare, okay? :D

    AntwortenLöschen
  25. Der Kommentar wurde von einem Blog-Administrator entfernt.

    AntwortenLöschen
  26. Der Kommentar wurde von einem Blog-Administrator entfernt.

    AntwortenLöschen
  27. Ich hab keine Ahnung :D

    AntwortenLöschen
  28. Hallo,

    wie kann ich das mit dem Zufall mit der gewünschte Punktzahl verbinden, damit mein Programm mir Aufgaben aussucht um die angegebene max. Punktzahl zu erreichen.

    AntwortenLöschen
  29. Grüße aus der Arbeit :D

    AntwortenLöschen