srand() und rand()

Gast #3329809
Lesenswert?

Hallo zusammen,

ich würde gerne auf einem ATMEGA 8 eine Zufallszahl generieren und habe 
damit keine Erfahrung. Ich würde dazu gerne srand() und rand() benutzen. 
Hierzu habe ich aber ein, zwei Fragen:
Liefert mir dieser Code immer neue Zahlen zwischen 0 und 9?
1
#define RAND_MAX 9
2
uint8_t zufallszahl;
3
uint32_t seed = 1;
4
srand(seed);
5

6
while(1)
7
{
8
zufallszahl = rand();
9
}

Gibt es auch eine Möglichkeit RAND_MAX dynamisch zu gestalten? 
Eigentlich brauche ich immer eine Zahl von 0-9 UND eine Zahl von 0-6.

Kann ich für seed auch einen Wert aus dem EEPROM wählen, den ich bei 
jedem Start erhöhe, damit die Werte nicht bei jedem Neustart identisch 
sind?
Gast #3329819
Lesenswert?

Bastel schrieb:
> Liefert mir dieser Code immer neue Zahlen zwischen 0 und 9?

Nein.

> #define RAND_MAX 9

RAND_MAX wird von der Implementation definiert und gibt an, in welchem 
Bereich rand() arbeitet. Du kannst jetzt an der Stelle zwar behaupten, 
dieser Wert wäre 9, aber rand() ist das ziemlich egal.

> Gibt es auch eine Möglichkeit RAND_MAX dynamisch zu gestalten?

Nein.

> Eigentlich brauche ich immer eine Zahl von 0-9 UND eine Zahl von 0-6.

Du kannst z.B. rand() % 9 machen. Dann ist deine Zahl im Bereich 0 bis 
9.

> Kann ich für seed auch einen Wert aus dem EEPROM wählen, den ich bei
> jedem Start erhöhe, damit die Werte nicht bei jedem Neustart identisch
> sind?

Ja. Genau um sowas zu machen ist srand() ja da.
Gast #3329843
Lesenswert?

Rolf Magnus schrieb:

> Du kannst z.B. rand() % 9 machen. Dann ist deine Zahl im Bereich 0 bis
> 9.

Wird wohl in diesem Falle ausreichend funktionieren, verzerrt aber etwas 
die Gleichverteilung, da i.d.R RAND_MAX kein Vielfaches von 10 ist.
Ein unrealistisches Extrembeispiel zur Verdeutlichung wäre RAND_MAX==15, 
da würden die Werte 0..5 doppelt so häufig rauspurzeln, wie 6..9.

besser (und wohl auch nicht aufwändiger) wäre wohl
ergebnis=rand()/RAND_MAX*WunschMax;
was aber einen breiteren Ergebnistyp (oder Gleitkomma, im µC wohl nicht 
so gut) erfordern würde. Nur mal so, zum im Hinterkopf behalten.
Modulodivision ist da etwas Ressourcenschonender.
nix für ungut...
#3329845
Lesenswert?

Und nur zur Ergänzung: Sofern der "Wunschzielbereich" den "tatsächlichen 
Zielbereich von rand()" fast ausfüllt, ist es meistens am einfachsten, 
einfach rand() solange aufzurufen, bis der Wert im gewünschten Bereich 
ist.

Das ist die einfachste Art, Verzerrungen der 
Wahrscheinlichkeitsverteilung zu vermeiden.
Gast #3329852
Lesenswert?

Ingo Wendler schrieb:
> besser (und wohl auch nicht aufwändiger) wäre wohl
> ergebnis=rand()/RAND_MAX*WunschMax;
> was aber einen breiteren Ergebnistyp (oder Gleitkomma, im µC wohl nicht
> so gut) erfordern würde.

Den Ergebnistyp nicht unbedingt, aber das Zwischenergebnis für 
RAND_MAX*WunschMax muß halt größer als int sein, um den Wert aufnehmen 
zu können, auf dem AVR also 32 Bit.

> Modulodivision ist da etwas Ressourcenschonender.

Deshalb hatte ich die auch vorgeschlagen.
Gast #3329854
Lesenswert?

Bastel schrieb:
> Kann ich für seed auch einen Wert aus dem EEPROM wählen, den ich bei
> jedem Start erhöhe, damit die Werte nicht bei jedem Neustart identisch
> sind?

Du kannst auch folgende Funktion verwenden
1
#include <avr/io.h>
2
 
3
unsigned short get_seed()
4
{
5
   unsigned short seed = 0;
6
   unsigned short *p = (unsigned short*) (RAMEND+1);
7
   extern unsigned short __heap_start;
8
    
9
   while (p >= &__heap_start + 1)
10
      seed ^= * (--p);
11
    
12
   return seed;
13
}
Quelle: 
http://www.rn-wissen.de/index.php/Zufallszahlen_mit_avr-gcc#Startwert_.28seed.29_besorgen

Der RAM ist nach einschalten in einem nicht-definierten Zustand (sofern 
nicht selber initialisiert) und somit bekommt man mit sehr hoher 
wahrscheinlichkeit nicht 2x hintereinander den gleichen seed.
#3329866
Lesenswert?

Bastel schrieb:
> Kann ich für seed auch einen Wert aus dem EEPROM wählen, den ich bei
> jedem Start erhöhe, damit die Werte nicht bei jedem Neustart identisch
> sind?

Im Prinzip schon, aber mit Zufall hat das Ergebnis dann nichts zu tun, 
sondern ist exakt reproduzierbar. Das kann egal sein, kann aber auch ein 
Problem sein, je nach Aufgabe.
Gast #3329935
Lesenswert?

Danke für den ganzen Input. Das Problem ist damit mehr als gelöst :)
Ich mache es mit rand() % 9. Für meine Anwendung ist die 
Wahrscheinlichkeitsverteilung und Reproduzierbarkeit völlig unkritisch.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren