Frage zur Modulo % Berechnung

OP #4247960
Lesenswert?
• ▲
▼
Hallo,

ich möchte ein "Würfelspiel" programmieren (im Atmel Studio Simulator) 
und mit dem folgenden Beispiel sehen, wie oft eine "zufällige Zahl" bei 
10000 Versuchen gewürfelt wurde.
Aber ich erhalte als Wert für zz immer 5"

Was mache ich falsch?
1
#include <stdlib.h>
2
#include <avr/io.h>
3

4
uint16_t zufallszahl, zz, wuerfelzahl, eins=0, zwei=0, drei=0, vier=0, fuenf=0, sechs=0;
5

6
int main(void)
7
{
8
  for (uint16_t i=0; i<10000; i++)
9
  {
10
    zufallszahl = rand();
11
    zz = zufallszahl % 6;
12
    wuerfelzahl = zz + 1;
13
    
14
    if (wuerfelzahl == 1)
15
      eins ++;
16
    else if (wuerfelzahl == 2)
17
      zwei ++;
18
    else if (wuerfelzahl == 3)
19
      drei ++;
20
    else if (wuerfelzahl == 4)
21
      vier ++;
22
    else if (wuerfelzahl == 5)
23
      fuenf ++;
24
    else if (wuerfelzahl == 6)
25
      sechs ++;
26
  }
27
}
Moderator (Firma: Titel) Persönliche Seite #4247982
Lesenswert?
• ▲
▼
m. g. schrieb:
> Was mache ich falsch?
Du initialisierst den Zufallsgenerator nicht mit einer Zufallszahl. Und 
rand() berechnet immer nur eine Zufallszahl aus der vorherigen 
Zufallszahl. Wenn du also immer mit 0 startest, kommt als nächste Zahl 
immmer 5...

Das Stichwort ist: seed()

Daniel A. schrieb:
> Am sichtbaren code liegt's nicht.
So ist es:
http://codepad.org/PZAlZSmo
Moderator Persönliche Seite #4247988
Lesenswert?
• ▲
▼
Lothar M. schrieb:
> m. g. schrieb:
>> Was mache ich falsch?
> Du initialisierst den Zufallsgenerator nicht mit einer Zufallszahl. Und
> rand() berechnet immer nur eine Zufallszahl aus der /vorherigen/
> Zufallszahl. Wenn du also immer mit 0 startest, kommt als nächste Zahl
> immmer 5...

Wo steht denn im Source, dass er immer mit 0 startet? Dann müsste er 
auch vor jedem rand() erst seed() mit 0 aufrufen. Tut er aber nicht. 
rand() berechnet die nächste Zufallszahl aus rand(). Wenn die immer 
gleich wäre, kannst Du rand() in die Tonne kloppen. Daher tippe ich 
weiter auf den Simulator, der schon in vielen AVR-Threads der böse Bube 
war.

Habe den obigen Source leicht geändert für Linux:
1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <stdint.h>
4

5
uint16_t zufallszahl, zz, wuerfelzahl, eins=0, zwei=0, drei=0, vier=0, fuenf=0, sechs=0;
6

7
int main(void)
8
{
9
  uint16_t i;
10

11
  for (i=0; i<10000; i++)
12
  {
13
    zufallszahl = rand();
14
    zz = zufallszahl % 6;
15
    wuerfelzahl = zz + 1;
16

17
    if (wuerfelzahl == 1)
18
      eins ++;
19
    else if (wuerfelzahl == 2)
20
      zwei ++;
21
    else if (wuerfelzahl == 3)
22
      drei ++;
23
    else if (wuerfelzahl == 4)
24
      vier ++;
25
    else if (wuerfelzahl == 5)
26
      fuenf ++;
27
    else if (wuerfelzahl == 6)
28
      sechs ++;
29
  }
30
  printf ("%d %d %d %d %d %d\n", eins, zwei, drei, vier, fuenf, sechs);
31
  return 0;
32
}

Ergebnis:
1
$ cc rand.c -o rand && ./rand
2
1655 1694 1761 1595 1671 1624

Also schön verteilt.
Gast #4247999
Lesenswert?
• ▲
▼
Das sagt Google dazu:
In der Bibliothek stdlib.h gibt es die Funktion rand(), welche eine 
Pseudo-Zufallszahl zurückgibt. Die Zahl liegt zwischen 0 und einer 
maximalen Zahl, welche mit der symbolischen Konstante RAND_MAX abgefragt 
werden kann. Möchte man den Bereich der Zufallszahl eingrenzen, kann der 
Modulo-Operator verwendet werden. Bevor die Zufallszahlen erstellt 
werden, sollte die Funktion srand() aufgerufen werden. Diese 
initialisiert den Zufallszahlen-Generator, um die Zufälligkeit der 
Zahlen zu gewährleisten. Im Parameter wird ein Zeitstempel übergeben, 
deshalb muss auch die time.h eingebunden werden.

http://www.c-howto.de/tutorial-uebungen-teil1.html
Moderator (Firma: Titel) Persönliche Seite #4248013
Lesenswert?
• ▲
▼
Piet schrieb:
> Bevor die Zufallszahlen erstellt werden, sollte die Funktion srand()
> aufgerufen werden.
Aber nur deshalb, weil sonst bei jedem Programmstart die gleiche 
Zufallszahlensequenz kommt.

Mit srand() gibts hier z.B. immer unterschiedliche Verteilung:
http://codepad.org/bYnXBNA2
http://codepad.org/KEhj5dr4

Ohne srand() immer die gleiche:
http://codepad.org/3Tb2LzcD
http://codepad.org/1cm5k5lq

Frank M. schrieb:
> Daher tippe ich weiter auf den Simulator, der schon in vielen
> AVR-Threads der böse Bube war.
Man müsste wissen, was rand() genau macht. Denn diese Funktion 
funktioniert hier offenbar nicht...
#4248046
Lesenswert?
• ▲
▼
Frank M. schrieb:
> m. g. schrieb:
>> Was mache ich falsch?
>
> Du vertraust zu sehr dem Simulator.

Muss nicht sein. Kann auch eine Fehlbedienung bzw. Fehlinterpretation 
sein.
Gerade Neulinge sind mit dem Wort 'dauernd' oft sehr voreilig.
Er steppt einmal durch den Code und kriegt eine 5. Dann steppt er in der 
Schleife weiter und die nächste von rand() gelieferte Zahl mündet wieder 
in einer 5 und schon ist das 'dauernd'.
Oder er startet das Programm neu und kriegt (no na) wieder als erste 
Würfelzahl eine 5.

Das rand() nicht funktioniert können wir wahrscheinlich ausschliessen. 
rand() ist keine Raketentechnik sondern simpel - und das 
plattformübergreifend.

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.