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
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.
> 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.
> 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.
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.
>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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.