Anfängerfrage zu Zufallszahlen

  • Anfängerfrage zu Zufallszahlen

    Hi,

    ich habe erst diese Woche angefangen mit dem Programmieren und bin deswegen noch dementsprechend unerfahren. Mein erstes Programm soll ein einfaches sein, dass per Zufall eine Lottozahl anzeigt.
    Habe das so realisiert bis jetzt:

    Quellcode

    1. - (IBAction)zahlenButton:(id)sender
    2. {
    3. int zz = (random() % 49)+1;
    4. [zahlenFeld setIntValue: zz];
    5. int aa = (random() % 49)+1;
    6. [zahlenFeld2 setIntValue: aa];
    7. int bb = (random() % 49)+1;
    8. [zahlenFeld3 setIntValue: bb];
    9. int cc = (random() % 49)+1;
    10. [zahlenFeld4 setIntValue: cc];
    11. int dd = (random() % 49)+1;
    12. [zahlenFeld5 setIntValue: dd];
    13. int ee = (random() % 49)+1;
    14. [zahlenFeld6 setIntValue: ee];
    15. }
    Alles anzeigen


    Mein Problem ist jetzt, dass manchmal gleiche Zahlen erscheinen. Wie kann ich es lösen, dass jede Zahl nur einmal erscheint? Ist für euch wahrscheinlich ein Klecks...sry für die Anfängerfrage ;)

    Dave
  • RE: Anfängerfrage zu Zufallszahlen

    Bei Zufallszahlen ist es immer wichtig, den Zufallsmechanismus neu zu initialisieren, das macht man mit srandom(long seed).

    Um bereits gezogenen Zahlen (Stichprobe ohne Zurücklegen) nicht mehr zu verwenden, muss Du diese manuell prüfen und ggf. neue Zahlen berechnen.
  • RE: Anfängerfrage zu Zufallszahlen

    Jepp, wie Snowman sagt, ist es das Problem, dass ein Zufallsgenerator innerhalb seiner Definition beliebige Zufallszahlen generiert. Daher können auch gleiche Zahlen kommen -- genauso wie in Wirklichkeit ein Würfel mehrfach die gleiche Zahl erzeugen kann.

    Entweder du machst es so wie Snowman gesagt hat und schaust in deinen bisherigen Ziehungen nach, ob die Zahl bereits vorhanden ist. Dann solltest du allerdings dringen die Zahlen in einem Feld speichern, weil du sonst mit ifs blöde wirst.

    Eine andere Möglichkeit, die ich etwass präferiere ist, dass du den Zahlenvorrate (1 bis 49) in ein Array ablegst und dann nach einer Ziehung das gezogene Element entfernst. Die nächste Ziehung wird dann nur noch auf die verbleibenden 48 Zahlen durchgeführt usw.

    Das hat den Vorteil, dass die programmtechnische Abbildung so ist wie in Wikrlichkeit, was für einen guten Stil spricht: Die "Kugel" fehlt.Außerdem ist ads flexibler, da du alles in eine Schleife packen kannst, also ohne weitere mehr als 6 aus 49 ziehen kannst. Das benötigst du aber nicht (oder doch MIttwochslotto?), weshalb es für dich kein Vorteil ist.

    Nachteil: Ich habe nie mathematisch nachgeprüft, ob das nicht die ZIehung beeinflusst.

    Ach, wo wir schon beim Thema sind: Ein einfaches Module stört die gleichmäßige Verteilung, wenn der Wertebereich des Genrators nicht ein Vielfaches des Modulos ist. Beispiel

    Generator 0 bis 9
    Module 7 (Spiel 77) 0 bis 6

    Dann erzeugst du
    0 -> 0
    1 -> 1
    2 -> 2
    3 -> 3
    4 -> 4
    5 -> 5
    6 -> 6
    7 -> 0
    8 -> 1
    9 -> 2

    0, 1 und 2 haben daher die doppelte(!) Wachrscheinlichkeit.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • also ich würde das in einer schleife durchgehen!

    Quellcode

    1. short gezogeneZahlen[6];
    2. INITRANDOM
    3. short i, zahl, pos = 0;
    4. while (pos < 7)
    5. {
    6. zahl = NEUE_RANDOMZAHL;
    7. for (i=0; i<pos; i++)
    8. {
    9. if (gezogeneZahlen[i]== zahl) goto exit;
    10. }
    11. gezogeneZahlen[pos] = zahl;
    12. pos++
    13. continue;
    14. exit:
    15. printf("Zahl schon vorhanden: %i\n",zahl);
    16. }
    Alles anzeigen


    das war jetzt nur so ein beispiel wie man das machen könnte. Welche art von arrays und zahlentypen und schleifen du verwendest ist dann eigenlich ganz egal.
    Das mit dem GOTO kannst du sicher auch anders lösen ;)
  • Das mit dem GOTO kannst du sicher auch anders lösen ;)

    Hehehe, gefällt dir selbst nicht? Ich erledige solche "umgekehrten" While-Schleifen, in dem ich das Ergebnis abfrage, gerne als for

    Quellcode

    1. for( i = 0; i < MAX_POS; i++ )
    2. if( ... == ... ) {
    3. break;
    4. }
    5. }
    6. if( i == MAX_POS ) {
    7. // Kein Duplikat
    Oder hier, wenn es nicht nur eine Abfrage ist:

    Quellcode

    1. i = 0;
    2. while( i != MAX_POS )
    3. for( i = 0; i < MAX_POS; i++ )
    4. zufall = ...
    5. if( zufall == feld[i] ) {
    6. break;
    7. }
    8. }
    9. }
    10. // Duplikatfreie Zahl gefunden
    So erspart man sich den goto.

    Um auch mal den anderen schematisch Ansatz vorzustellen:

    Quellcode

    1. int position;
    2. int zufall;
    3. NSMutableIndexSet* tipp = [NSMutableIndexSet indexSet];
    4. NSMutableIndexSet* numberSet = [NSMutableIndexSet indexSetInRange:NSMakeRange( 1, 49 )];
    5. for( position = 0; position < MAX_POSITION; position++ ) {
    6. zufall = [numberSet indexAtIndex: ... * [numberSet count] / ZUFALLSGENERATORBEREICH];
    7. [numberSet removeIndex:zufall]; // "verbrauchte" Zahl wegnehmen
    8. [tipp addIndex:zufall]; /7 Und zum Ergebnis hinzufügen
    9. }
    Alles anzeigen

    Ich find's halt eleganter. Ist aber sicher auch teilweise Geschmacksfrage. Mir gefällt es besser, dass der Vorgang des Entnehmens gut in der Source dokumentiert ist. Kürzer ist es auch noch. Das ist ja nict nur die Ermittlung einer Zufallszahl, sondern der ganzen Tippreihe.

    Anmerkung: Mit einem IndexSet ist es besser als mit einem Array. Es ist auch "richtiger", da Lottozahlen ungeordnet sind. Allerdings muss man möglicherweise die Zusatzzahl dann anders behandeln -- keine Ahung, ich tippe nicht.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Ein solcher Zufallszahlengenerator kennt keine Zufälle…

    Leider liefern alle diese Algorithmen keine echten Zufallszahlen. Deswegen nennt man sie "Pseudorandom". Leider. Nur die Verteilung ist gleichmäßig bei einer genügend großen Zahl von Ziehungen. Echte Zufallsgeneratoren werden derzeit mit Teilchenphysik hergestellt und mit dem Computer ausgewertet
    random.org/essay.html
    ist eine gute Quelle. Mit einem Soap Interface ausgestattet bekommt man echte Zufallszahlen geliefert.
  • Und was verbirgt sich hinter NEUERANDOMZAHL?
    Du gibst doch einfach die äußere Schleife wieder?

    (BTW: Mein Hinweis bezog sich ja auf das Problem des goto in der iterativen Lösung. Meine ist ja eine ganz andere.)

    Aber wieso findest du einen while schöner als einen for?
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • das mit dem goto habe ich nur übersichtsheitshalber gemacht.

    hat doch verständlicher ausgesehen als das hier:

    Quellcode

    1. short gezogeneZahlen[6];
    2. INIT_RANDOM
    3. short i, zahl, pos = 0;
    4. while (pos < 7)
    5. {
    6. zahl = NEUE_RANDOMZAHL;
    7. for (i=0; i<pos; i++)
    8. {
    9. if (gezogeneZahlen[i]== zahl) break;
    10. }
    11. if (i==pos)
    12. {
    13. gezogeneZahlen[pos] = zahl;
    14. pos++
    15. continue;
    16. }
    17. printf("Zahl schon vorhanden: %i\n",zahl);
    18. }
    Alles anzeigen



    Mein code vom letzten beitrag gefällt mir einiges besser als deiner hier:

    Quellcode

    1. int position;
    2. int zufall;
    3. NSMutableIndexSet* tipp = [NSMutableIndexSet indexSet];
    4. NSMutableIndexSet* numberSet = [NSMutableIndexSet indexSetInRange:NSMakeRange( 1, 49 )];
    5. for( position = 0; position < MAX_POSITION; position++ ) {
    6. zufall = [numberSet indexAtIndex: ... * [numberSet count] / ZUFALLSGENERATORBEREICH];
    7. [numberSet removeIndex:zufall]; // "verbrauchte" Zahl wegnehmen
    8. [tipp addIndex:zufall]; /7 Und zum Ergebnis hinzufügen
    9. }
    Alles anzeigen
  • Hmmm, stimmt. Ich finde es halt ein Zählproblem und bemühe mich immer meine Source so zu halten, dass sie das Problem abbildet. Also, wenn ich "der Sache nach" zähle, dann ein for, wenn ich "der Sache nach" auf eine Bedingung wate, ein while. Ist aber sicher auch Geschmacksfrage. Und bei diesem Snipplet dürfte es übersichtlich bleiben. ;)
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?