Forum: Mikrocontroller und Digitale Elektronik Zufallszahlen


von Basti (Gast)


Lesenswert?

Hallo,
ich soll in C eine zufallszahl generieren, die einer Zeit von 0 bis 1
Sekunde entspricht. Mit der rand Funktion bekomme ich auf jedenfall
eine Zufallszahl heraus. Kriege diese jedoch nicht unter eine
Sekunde???
Ist es auch richtig wenn ich iin der srand Funktion einen Wert mit
einem Timer hochzählen lasse, dass ich damit den Startwert beeinflusse
und somit die Zufallszahl?

Danke im vorraus

von Karl H. (kbuchegg)


Lesenswert?

Warum kriegst du die Zahl nicht unter 1 Sekunde?

rand() liefert dir eine Zahl im Bereich 0 bis RAND_MAX.
Die Division ist schon erfunden.

von Karl H. (kbuchegg)


Lesenswert?

> Ist es auch richtig wenn ich iin der srand Funktion einen Wert
> mit einem Timer hochzählen lasse, dass ich damit den Startwert
> beeinflusse und somit die Zufallszahl?

Nein. Das ist nicht richtig. Du sollst mittels srand() den
Zufallszahlengenerator einmal initialisieren und dann den
'Seed' in Ruhe lassen. Nur so hast du überhaupt eine Chance
dass die Zahlen die rand() liefert auch nur irgendwas ähnliches
wie Zufallszahlen sind.

Im Rechner gibt es keine Zufallszahlen (ausser man benutzt
thermisches Rauschen an Dioden oder so. Ist aber alles
extrem aufwändig). Daher behilft man sich so: Es gibt eine
Formel bei der man die letzte Zufallszahl hineinstopft und
dafür die nächste Zufallszahl herauskriegt. Bei der nächsten
Anforderung geht dieses alte Ergebnis wieder in die Formel
ein und man kriegt das nächste Ergebnis. Die Kunst besteht
nun darin, eine Formel zu finden, so dass die generierten
Zahlen die statistischen Eigenschaften von Zufallszahlen haben.
Dazu musst du aber die Formel arbeiten lassen. Wenn die
mittels srand() da immer wieder eingreifst, zerstörst du
die Statistik und deine Zahlen sind Mist.

von Unbekannter (Gast)


Lesenswert?

> Im Rechner gibt es keine Zufallszahlen

Du meinst zwar im Prinzip das richtige, aber die Aussage ist doch etwas
zu allgemein.

Man sollte vielleicht besser sagen, dass es in den meisten
(einfacheren) Rechnern keine Zufallszahlen gibt.

Aber schon bei einem einfach PC, gibt es Quellen für taugliche
Zufallszahlen.

Da wäre z.B. das Timing von empfangen Netzwerkpakete beim
Internet-Surfen. Oder das Timing von Festplattenzugriffen oder das
Timing von Tastatur- und Mausereignissen etc.

Jeder diese Vorgänge bietet ein paar Bits oder auch weniger
"Zufallsinformation". Zwar nur sehr wenig, aber immerhin.

Aber richtig ist, dass Library-Funktionen wie rand() etc. diese
Zufallsquellen nicht benutzen, sondern eine Algorithmus, wie Du ihn
beschrieben hast, verwenden.

Deshalb nennen sich solche Funktionen auch Pseudo-Zufallsgenerator.

Echte Zufallzahlen gibt es unter vernüftigen Betriebssystemen z.B.
unter /dev/random.

von Christoph W. (christoph)


Lesenswert?

Bau dir einen alternativen Zufallsgenerator. Für µC und Co. zum Beispiel
hab ich mal einen Roulette-Zufallsgenerator auf einem Shift-XOR-Register
aufgebaut :

;**************************************** WAIT TIMER
RANDOM:       ; Zufallszahl beschreiben   ( RANDOM )
    cli
  RANDOM_AGAIN:
    ldi  TEMP2,0
    call  RANDOM_BIT
    lsl  TEMP2
    call  RANDOM_BIT
    lsl  TEMP2
    call  RANDOM_BIT
    lsl  TEMP2
    call  RANDOM_BIT
    lsl  TEMP2
    call  RANDOM_BIT
    lsl  TEMP2
    call  RANDOM_BIT

    cpi  TEMP2,37
    brsh  RANDOM_AGAIN
    mov  RANDOM,TEMP2

    sei
    ret

RANDOM_BIT:      ; erzeugt zufälliges Bit -> TEMP2.0
    ldi  ZH,0x35
    ldi  ZL,00

    bclr  0
    andi  TEMP2,0b11111110; Result := 0
    sbrc  SR1,0
    bset  0
    brcc  RB_ROLL
    ori  TEMP2,0b00000001; Result := 1

    lpm  TEMP1,Z+
    eor  SR1,TEMP1
    lpm  TEMP1,Z+
    eor  SR2,TEMP1
    lpm  TEMP1,Z+
    eor  SR3,TEMP1
    lpm  TEMP1,Z+
    eor  SR4,TEMP1
    lpm  TEMP1,Z+
    eor  SR5,TEMP1
    lpm  TEMP1,Z+
    eor  SR6,TEMP1
    lpm  TEMP1,Z+
    eor  SR7,TEMP1
    lpm  TEMP1,Z+
    eor  SR8,TEMP1

  RB_ROLL:
    ror  SR8
    ror  SR7
    ror  SR6
    ror  SR5
    ror  SR4
    ror  SR3
    ror  SR2
    ror  SR1

    ret


Auf der Addresse "0x3500" liegt ein Maskendwort :
    .db  0b01010110,0b00000000  ; L,ML
    .db  0b00000000,0b10000000  ; MH,H
    .db  0b00100110,0b00000000  ; L,ML
    .db  0b00000000,0b00001000  ; MH,H



Random_Bit erzeugt ein Zufallsbit, Random eine Zufallszahl. Als Ausgang
wird ein 64bit Register (SR1-8) verwendet, also recht unwahrscheinlich,
dass da viel Murks passiert. Als Startwert kannst du SR1-SR8 nach dem
Power-On des µCs mit Werten aus dem SRAM befüllen Diese sind dann
physikalisch schon absolut zufällig.

Diese Technik ist relativ schnell, speichersparend und ziemlich
Zufallssicher. Je kleiner das Register (SR1-8), desto schneller
arbeitet der Algo. Allerdings leidet der Zufall dann darunter. Für ein
32bit-Register einfach nur die ersten 4 Maskenbytes verwenden.

von R2D2 (Gast)


Lesenswert?

>Als Startwert kannst du SR1-SR8 nach dem
Power-On des µCs mit Werten aus dem SRAM befüllen Diese sind dann
physikalisch schon absolut zufällig.

Ich denke das stimmt so nicht. Ich hab z.B. festgestellt das sich die
Werte besonders bei nicht allzulangen off-zeiten kaum bis nicht ändern.
Sicher, es ist besser als nix, aber es gibt andere Methoden:
1. Offener ADC eingang mit einem Stück leiterbahn dran. Fängt alle
möglichen Störungen ein. Alternativ kann man noch ne Diode mit hoher
Rauschspannung oder ähnliches anschließen.
2. Wenn es Interaktion mit dem User gibt: Schnell laufenden Timer
verwenden und die Zeit zwischen zwei Tastendrücken messen.
3. Vor den Ausschalten die letzte Pseudozufallszahl im EEPROM
speichern. Ist zwar nicht mehr wirklich zufällig, aber man weiß
wenigstens sicher, dass es irgendwo los geht, wo sinnvolle daten
stehen. Im SRAM stehen mit etwas Pech lauter 0en. Diese Methode eignet
sich auch gut für 2. als Ergänzung um die Zeit bis zum ersten
Tastendruck zu überbrücken.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.