Hallo,
Ich programmiere derzeit einen ATMega8, und bräuchte jetzt eine
Funktion, die Zufallszahlen zwischen 0 und 20 generiert.
Muss ich dafür irgendwelche Dateien includen?
Kann mir wer verraten, wie ich eine solche Zufallszahl generiere?
Wie ich aber wirklich eine Zufallszahl (sei es ne Pseudozufallszahl)
erstelle, steht da aber nicht? :O
optimal möchte ich ein Zufallsbit erstellen, mit ner Wahrscheinlichkeit
von 30%, dass es ne 0 und 70%, dass es ne 1 ist.
doedel schrieb:> für welchen der aufgezählten Ansätze hast Du Dich denn entschieden?
Beide wären hilfreich zu wissen.
Felice Dalice schrieb:> #include <stdlib.h>>> main(){> int zahl=rand()%10;> if(zahl<3)> zahl=0;> else> zahl=1;> }
Danke, werde ich gleich einmal austesten.
=rand()%10; den befehl kannte ich zum beispiel garnicht.
Felice Dalice schrieb:> #include <stdlib.h>>> main(){> int zahl=rand()%10;> if(zahl<3)> zahl=0;> else> zahl=1;> }
Ich mein natürlich
int zahl=rand()%20;
if(zahl<6)
hatte mit 10 gerechnet
die Verwendung von rand() führt aber immer zur gleichen Abfolge von
Zufallszahlen ... und zur Verwendung von srand() fehlt wohl ein
geeigneter Seed-Wert
ahhh .. und dann überlegen wir doch mal, was time() auf einem ATMEGA
ohne RTC liefert? Na? Da der Start-Prozess immer gleich lang dauern
sollte wird auch time() immer den gleichen Wert liefern und damit auch
rand()
Wenn Du keine Zeit auf dem uC hast:
Nimm anstelle der Zeit einfach einen ADC, der nur Rauschen aufnimmt.
Wenn man das fein genug einstellt, sollte es zumindest deutlich besser
werden.
super Markus ... 100 Punkte! Und damit sind wir wieder beim Artikel über
die Zahlfallszahlen. Dort wird die Verwendung des ADC nicht nur für die
Erzeugung eines Seed Wertes verwendet sondern gleich für die Erzeugung
der Zufallszahl. Es macht ja sonst auch keinen Sinn, eine Zufallszahl
auf einem Weg zu erzeugen, nur um dann weitere Zufallszahlen auf einem
anderen Weg zu generieren.
Und damit sind wir wieder bei meiner Frage an den TO: für welchen Ansatz
aus dem Beitrag hast Du Dich denn entschieden?
Wie "teuer" ist es denn, auf einem MC Standardlibraries zu nutzen?
Pseudozufallszahlen-Folgen direkt mit nem rückgekoppelten
Schieberegister zu erzeugen, nachdem man das ganze zufällig genug
initialisiert hat, wäre vielleicht etwas sparsamer.
das Problem ist schlichtweg, dass es für alle Standard-Verfahren
erforderlich ist, diese mit einem Zufallswert zu initialisieren - und
genau da liegt das Problem bei Verwendung eines uC. Auf dem PC macht man
sich das einfach und verwendet die aktuelle Uhrzeit - wie oben ja schon
beschrieben wurde. Diese ist als Initialisierungs-Wert üblicherweise
ausreichend zufällig. Auf einem uC sieht es (ohne RTC) aber anders aus.
In dem Moment wo ich ihn anschalte oder resete, fängt der Uhr bei 0 an.
Da die "Boot-Abfolge" im Idealfall aber immer gleich lang dauert, wird
die Initialisierung aus Sicht der uC-Uhr immer zum selben Zeitpunkt
erfolgen und ist damit nicht mehr ausreichend zufällig.
Die "Standard-Methode" dürfte im uC-Bereich tatsächlich das Auslesen
eines rauschenden Signals mit dem ADC sein. Wenn ich das aber schon mal
mache um einen zufälligen Initialisierungs-Wert zu erhalten, kann ich
die gleiche Methode auch gleich verwenden um alle folgenden Zufallswerte
zu erzeugen.
Ich will hier keinem ausreden rand() + srand() aus den
C-Standard-Bibliotheken zu verwenden. Ich möchte nur erreichen, dass man
sich Gedanken um die Besonderheiten der Verwendung auf dem uC macht und
dass das halt kein PC ist.
Man könnte auch zum Testen die Dauer eines Tastendrucks oder die Zeit
bis zum Tastendruck messen. Das ist nicht perfekt zufällig, aber zum
Ausprobieren sicher gut genug.
Na da habt ihr natürlich recht. Kenn mich mit dem ATMega8 nicht aus.
Also meine Variante kannst du dann machen wenn du das von außen
triggerst. Also du drückst nen Knopf und dein Prozessor gibt dir dann ne
30:70 verteilung aus. dann bist du der zufall wann du den Knopf drückst.
mit dem ADC klingt gut find ich wenn du die zahlen automatisch berechnen
willst.
Aber da scheint es ja nen Thread zu geben wo das beschrieben wird
@Dussel: auch das ist eine der im oben verlinken Artikel aufgeführte
Methode :-) erfordert aber halt eine (zufällige) Aktion von Außen, auf
die ich im Code reagieren kann.
Um mich zu outen: wenn sich die Möglichkeit dazu bietet, ist das mein
persönlicher Favorit ;-)
Felice Dalice schrieb:> Na da habt ihr natürlich recht. Kenn mich mit dem ATMega8 nicht aus
Tja, allen anderen war das spätestens nach deinem 2. Beitrag klar. Aber
hier werden sie geholfen, auch du...
Oliver
Max H. schrieb:> Wozu wird der Zufall benötigt? Wenn ein Mensch das Gerät bedient könnte> man aus den Zeitpunkt eines Tastendrucks Zufall generieren.
Zufall wird dafür benötigt, dass zu 70% ne 0, zu 30% ne 1 in ein
Schieberegister geschoben wird, welche dann Led´s ansteuern, was ja aber
unwichtig sein dürfte.
Eine andere Variante besteht noch darin, sich den Seed im EEPROM zu
speichern. Nach jedem Starten erhöht man den Seed, speichert ihn erneut
im EEPROM und gibt ihn per srand an den Default-Generator weiter. So hat
man für jeden µC-Start unterschiedliche Seed Werte.
Für ein Lauflicht ist das mit Sicherheit gut genug.
> was ja aber unwichtig sein dürfte.
Nicht ganz. Es macht schon einen Unterschied, ob die 'Zufallszahlen' ein
paar LED blinken lassen, oder ob damit ein Geld-Spielautomat betrieben
wird. Für ersteres reicht das simpelste vom simplen. Für letzteres aber
nicht.
Mike schrieb:> Zufallszahlen bei Geldspielautomaten?? Das macht doch gar keinen Sinn.> Seit wann läuft in einem Spielautomat ein Zufallsgenerator?
Bei ZufallsSpielautomaten hehe ;)
Da schmeißt man n Euro rein, bekommt zu 10% 2 Euro und zu 90% nichts,
nein Spaß beiseite
Habe nun folgendes Programm geschrieben,
Die Funktion Test() wird natürlich im Main aufgerufen, und dann werden
die Bits von bitarray[][] in ein SR geschoben.
Komischerweise ist die Zahl, die die Funktion ZufallsBits zurückgibt
immer 0b00001, oder 0b00000.
alle anderen Bitkombinationen werden nie erstellt?
Wo ist mein Denkfehler..
1
charZufallsBits(zahl)// liest pseudozufällig bits ein
Mike schrieb:> Zufallszahlen bei Geldspielautomaten?? Das macht doch gar keinen Sinn.
Das ist das einzige, was "Sinn macht". Was soll der Automat denn sonst
machen?
Siehe
http://www.onlinecaXsinodeutsch.info/nachrichten/news_zufallsgeneratoren.php
(Das X aus dem Link entfernen, ohne hat das Forum mein Posting leider
als Spam abgelehnt)
> Seit wann läuft in einem Spielautomat ein Zufallsgenerator?
Schon immer?
Oliver S. schrieb:> Fragensteller schrieb:>> else if(42 <= zahl < 50)>> Du brauchst ein C-Buch.
Mal abgesehen davon frage ich mich auch, warum da überhaupt die voher
schon geprüfte Obergrenze des Bereichs nochmal auftaucht.
Ich blick hier langsam die Anforderungen nicht mehr. Erst soll es eine
Zufallszahl zwischen 0 und 20 sein. Dann soll es eine Zufallszahl
zwischen 0 und 1 sein, mit 30%iger Wahrscheinlichkeit für 0 und 70%iger
Wahrscheinlichkeit für 1. Das zuletzte gepostete Codebeispiel macht dann
wieder irgendetwas Anderes, und das offensichtlich auch noch falsch
Soweit ich sehe wurden 2 Dinge bisher nicht erwähnt:
1. Die Modulo-Division (z.B. rand()%20) ist nicht optimal, wenn man
Zufallszahlen z.B. von 0 bis 19 möchte. Grund ist, dass der Wertebereich
der rand-Funktion kein Vielfaches von 20 ist. Es gibt daher 2 Gruppen
von Ergebniszahlen die sich geringfügig in der Wahrscheinlichkeit
unterscheiden.
Um die 30/70-Proportion des Threadstarters einzuhalten ist es genauer,
einen Vergleich bei 30% von RAND_MAX zu machen als vorher %10 und dann
>=3.
2. Wenn es um wirklich guten Zufall geht: Der AD-Wandler kann auch
nicht-zufällige Problemchen haben. Intel hat da ein schönes Paper
geschrieben, als sie einen Zufallszahlengenerator in die CPU eingebaut
haben. Wenn ich mich recht errinnere schlagen sie einen Mixer vor. Das
ist ein Entropiepuffer, aus dem ein paar Bits Zufall entnommen werden
dürfen, der aber wieder mit echten Bits vom AD-Wandler aufgefüllt wird.
Danach wird geschüttelt, indem man den Entropiepuffer mit einer
Hash-Funktion auf sich selbst abbildet.
Das Paper: http://www.cryptography.com/public/pdf/IntelRNG.pdf
Grüße, Joey
Bei Intel gehts um kryptographisch starke Zufallszahlen, hier im Thread
nur um "Spielzeug-Zufall". Da sind diese Effekte wurscht.
Für Kryptokram kann man das ADC-Samplen auch gleich sein lassen.
Joey, bitte machs nicht komplizerter als notwendig.
Der TO kämpft mit ganz anderen Dingen als mit qualitativ höchstwertigen
Zufallszahlen, sieh dir sein Programm an.
Bei ihm spielt dieser kleine Fehler keine große Rolle und er wird ihn in
seinen "Lichtshows" nie bemerken.
Fred schrieb:> Bei Intel gehts um kryptographisch starke Zufallszahlen, hier im Thread> nur um "Spielzeug-Zufall". Da sind diese Effekte wurscht.>> Für Kryptokram kann man das ADC-Samplen auch gleich sein lassen.
Ja, das ist mir schon klar. Und für sein LED-Blinken ganz ganz weit über
das Ziel hinausgeschossen.
Ich freue mich immer, wenn mehr Background-Info angeboten wird. Es lesen
ja auch andere mit, die vielleicht mal was anderes machen als mit LEDs
zu blinken. Dann ist es toll wenn die wissen, dass es bei Zufallszahlen
noch mindestens 2 Level mehr gibt.
Joey5337 schrieb:> Ich freue mich immer, wenn mehr Background-Info angeboten wird.
Wenn die Hintergrund-Infos aber nichts zum eigentlichen Thread-Thema
beitragen, dann sind sie eher störend - vor allem dann, wenn sie immer
und immer wieder eingestreut werden.
Mach doch einen eigenen Thread auf mit dem Thema:
"Was sind gute Zufallszahlen?"
Dort wäre es wesentlich angemessener, Dein geballtes Wissen
hinauszuschreien. Wenn ich in ein paar Jahrzehnten wissen will, wie ich
für meinen Anwendungsfall optimale Zufallszahlen erzeugen kann, werde
ich gewiss NICHT diesen Thread bis zum Ende durchlesen. "Ach, der will
hier nur LEDs blinken lassen..." -> weg damit und zum nächsten Thread in
der Suchliste.
Einem gesonderten Thread mit dem Titel
"Was sind gute Zufallszahlen?"
würde ich als bei der Suche nach guten Zufallszahlen wesentlich mehr
Aufmerksamkeit schenken.
Also hör bitte auf, diesen Thread hier zu verwässern, mach Deinen
eigenen auf.
Da bei AVR randmax so definiert ist,
#define RAND_MAX 0x7FFF
kann man sowas machen:
int myrand(int max) {
unsigned long rnd;
rnd=rand()<<1;
rnd*=max;
return rnd>>16;
}
Ihr seid lustig...
ich dachte, es geht hier auch ein bischen um Spaß und niveauvolle
Unterhaltung. Die Verweise auf xkcd, diehard-Tests und
Geldspielautomaten fallen doch ganz klar in diese Kategorie.
Wenn es wirklich so sehr um die Verwässerung des Threads geht, wäre es
vielleicht besser gewesen die Füße still zu halten und meinen ersten
Beitrag einfach zu ignorieren. Jetzt haben wir schon 5
"Meta"-Beiträge...
putter schrieb:> Joey5337 schrieb:>> Jetzt haben wir schon 5>> "Meta"-Beiträge...>> Und der TO hat es immer noch nicht geschafft seine LEDs blinken zu> lassen........
er hat es ja auch noch nicht geschafft, sich mit sich selbst zu einigen,
was eigentlich das Ziel der ganzen Sache ist. Wenn sich die
Anforderungen dauernd ändern, was eigentlich mit diesen Zahlen passieren
soll .....
Na, deshalb meldet er sich jetzt auch erstmal nicht, sondern wartet ab.
Vielleicht passen die sich ständig ändernden Anforderungen ja irgendwann
mal zufällig zu seinem bereits existierenden Code.
Eine Art von "predictive coding".
Oliver S. schrieb:> Fragensteller schrieb:>> else if(42 <= zahl < 50)>> Du brauchst ein C-Buch.
Ok, dass er die Obergrenze nochmal abprüft ist unnötig,
aber sonst ist das doch korrekt? Warum sollte er da ein C Buch brauchen?
Jay schrieb:> Oliver S. schrieb:>> Fragensteller schrieb:>>> else if(42 <= zahl < 50)>>>> Du brauchst ein C-Buch.>> Ok, dass er die Obergrenze nochmal abprüft ist unnötig,> aber sonst ist das doch korrekt? Warum sollte er da ein C Buch brauchen?
Soweit ich weiß, ist das Verhalten nicht definiert, aber vor Allem ist
das wahrscheinlich nicht das, was er wollte.
Jay schrieb:> Dussel schrieb:>> Soweit ich weiß, ist das Verhalten nicht definiert,>> Was fürn Verhalten ist nicht definiert?
Ich meine das Ergebnis der Bedingung, nicht Verhalten.
Wenn die Operatoren von links nach rechts ausgeführt werden und wenn
'true' '1' ist, ist "42<=1" '0' oder '1' und damit immer kleiner als 50.
Allerdings bin ich nicht sicher, ob 'true' immer '1' ist.
Ein kleines Relais als Selbstschwinger (über den Öffnerkontakt) und am
Schliesserkontakt oder über direkte, spannungsbegrenzte Auskopplung, die
Prellimpulse pro Zeitspanne zählen. Das Ganze dann per Modulo in die
gewünschte Range drücken... ob der Zähler dabei x-mal überläuft ist auch
schnuppe. Die Zähl-Zeitspanne könnte man auch noch über den
vorhergehenden Zufalls-Zählerstand zusätzlich "zufallisieren", damit es
echt sowas von zufällig ist. ;-)
A propos Zufall bei Geldspielautomaten:
Ich hab vor zig Jahren mal als Servicetechniker für Spielgeräte
gearbeitet. Damals waren da die überlichen 8-Bitter (Zilog und Mot)
verbaut und die PTB hatte festgelegt, dass innerhalb einer gewissen
Spieleanzahl (glaub 60.000) eine Auszahlqoute von mindestens 60%
garantiert sein musste. Das wurde natürlich nur mit
Pseudo-Zufallsgeneratoren und sequenziellem Spielplan erreicht.
Die wurden dann nach Bekantwerden des Prinzips irgendwann geknackt und
reihenweise die Automaten geleert, indem man die hintereinander
auftretenden Gewinnkombinationen aufgeschrieben hat und dann mittels PC
und geknacktem Code rausfinden konnte, wo das Programm gerade stand und
wie es weitergeht. Daraufhin wurde es von der PTB erlaubt, dass zwischen
mehreren verschiedenen 60%-Pseudo-Zufallsgeneratoren bei jedem
Münzeinwurf hin und her gesprungen werden durfte, so dass es
entsprechend schwieriger wurde, den Stand der gerade aktiven
Zufallsmaschine zu errechnen und korrekte Voraussagen zu treffen.
Es waren übrigens sowohl die Stellung der Rotationskörper, wie auch die
Erfolgsaussichten der Zufalsleiter im Code vorherbestimmt und somit
unabhängig vom Timing des Tastendrucks des Spielers.
Dussel schrieb:> Jay schrieb:>> Dussel schrieb:>>> Soweit ich weiß, ist das Verhalten nicht definiert,>>>> Was fürn Verhalten ist nicht definiert?> Ich meine das Ergebnis der Bedingung, nicht Verhalten.
Doch, doch. Das passt schon. Das Verhalten ist exakt definiert.
> Wenn die Operatoren von links nach rechts ausgeführt werden
Diesen Satz brauchst du nicht mit 'Wenn' anfangen lassen.
Auch das ist in C exakte definiert.
Ist man sich bei der Abarbeitung von Operatoren nicht ganz sicher (was
vorkommen kann), dann sieht man entweder in sein C Buch, oder man
googelt nach 'Operator precedence table'. Der entnimmt man, dass die
kleiner/größer/kleiner gleich/größer gleich Vergleichsoperatoren alle
die gleiche Priorität haben (die höher ist als == bzw. !=) und dass sie
von links nach rechts angewendet werden.
Somit kannst du in deinem Satz das 'wenn' ersatzlos streichen. Die Sache
verhält sich tatsächlich und definiert genau so, wie du es beschreibst.
> und wenn> 'true' '1' ist,
An dieser Stelle kannst du ebenfalls das 'wenn' streichen. Wenn es der
Fall ist, dass das System einen Wahrheitswert tatsächlich generieren
muss (wie in dem Fall, dass mit dem Ergebnis eines Vergleichs weiter
gerechnet wird), dann gilt: logisch false wird durch 0 repräsentiert,
logisch true wird durch 1 repräsentiert. Auch das ist genau so
definiert, so dass du das 'wenn' in deinem Satz ersatzlos streichen
kannst.
Der Rest deiner Ausführengen ist korrekt und auch korrekt hergeleitet.
Lediglich die Unsicherheit in den 'wenn' kannst du streichen. Das ist
alles genau so definiert, wie du es angenommen hast - wodurch aus dem
'ist nicht definiert' ein 'das Verhalten ist genau definiert und verhält
sich so, wie du es in weiterer Folge herleitest' wird.
Danke für die Aufklärung. Sicher war ich mir nicht mit der
Auswertereihenfolge der Operatoren und ob eben 'true' 1 ist. Jede Zahl
größer 0 (oder ungleich null?) wird ja als 'true' interpretiert, deshalb
wusste ich nicht, ob das umgekehrt auch so gilt.
In dem gegebenen Beispiel war das Verhalten wahrscheinlich aber nicht so
gewünscht.