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?
einfach mal Forum und Artikelsammlung durchsuchen! http://www.mikrocontroller.net/articles/Zufallszahlen
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.
#include <stdlib.h> main(){ int zahl=rand()%10; if(zahl<3) zahl=0; else zahl=1; }
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
naja rand() gibt dir nen Random integer wieder und mit % sorgst du dafür das der zwischen 0>=zahl<20 liegt
so machen die das auf c++ referenz http://www.cplusplus.com/reference/cstdlib/rand/ /* initialize random seed: */ srand (time(NULL));
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()
Felice Dalice schrieb: > srand (time(NULL)); wenn du denn eine Zeit auf dem Mikrocontroller hast...;-)
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
Wozu wird der Zufall benötigt? Wenn ein Mensch das Gerät bedient könnte man aus den Zeitpunkt eines Tastendrucks Zufall generieren.
@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
Alles viel zu kompliziert. Die Profis von XKCD machen das so
1 | int getRandomNumber() |
2 | {
|
3 | return 4; // chosen by fair dice roll. |
4 | // guaranteed to be random.
|
5 | }
|
:D
xkcd schrieb: > Alles viel zu kompliziert. Die Profis von XKCD machen das so > >
1 | int getRandomNumber() |
2 | > { |
3 | > return 4; // chosen by fair dice roll. |
4 | > // guaranteed to be random. |
5 | > } |
> > :D stimmt bei mir steht return 6; muß Zufall sein ;-)
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.
:
Bearbeitet durch User
Zufallszahlen bei Geldspielautomaten müssen vieles aushalten ... Diehard .... http://en.wikipedia.org/wiki/Diehard_tests
Zufallszahlen bei Geldspielautomaten?? Das macht doch gar keinen Sinn. Seit wann läuft in einem Spielautomat ein Zufallsgenerator?
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 | char ZufallsBits(zahl) // liest pseudozufällig bits ein |
2 | {
|
3 | if(50 <= zahl) |
4 | {
|
5 | return 0b00000; |
6 | }
|
7 | else if(42 <= zahl < 50) |
8 | {
|
9 | return 0b10000; |
10 | }
|
11 | else if(34 <= zahl < 42) |
12 | {
|
13 | return 0b01000; |
14 | }
|
15 | else if(26 <= zahl < 34) |
16 | {
|
17 | return 0b00100; |
18 | }
|
19 | else if(18 <= zahl < 26) |
20 | {
|
21 | return 0b00010; |
22 | }
|
23 | else if(10 <= zahl < 18) |
24 | {
|
25 | return 0b00001; |
26 | }
|
27 | else
|
28 | {
|
29 | if(zahl==9) |
30 | {
|
31 | return 0b11000; |
32 | }
|
33 | else if(zahl==8) |
34 | {
|
35 | return 0b10100; |
36 | }
|
37 | else if(zahl==7) |
38 | {
|
39 | return 0b10010; |
40 | }
|
41 | else if(zahl==6) |
42 | {
|
43 | return 0b10001; |
44 | }
|
45 | else if(zahl==5) |
46 | {
|
47 | return 0b01100; |
48 | }
|
49 | else if(zahl==4) |
50 | {
|
51 | return 0b01010; |
52 | }
|
53 | else if(zahl==3) |
54 | {
|
55 | return 0b01001; |
56 | }
|
57 | else if(zahl==2) |
58 | {
|
59 | return 0b00110; |
60 | }
|
61 | else if(zahl==1) |
62 | {
|
63 | return 0b00101; |
64 | }
|
65 | else if(zahl==0) |
66 | {
|
67 | return 0b00011; |
68 | }
|
69 | }
|
70 | }
|
71 | void Test() |
72 | {
|
73 | unsigned char testchar=rand()%100; |
74 | |
75 | bitarray[0][0]=ZufallsBits(testchar); |
76 | }
|
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.
:
Bearbeitet durch Moderator
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...
Joey5337 schrieb: > Jetzt haben wir schon 5 > "Meta"-Beiträge... Und der TO hat es immer noch nicht geschafft seine LEDs blinken zu lassen........
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.
Dussel schrieb: > Soweit ich weiß, ist das Verhalten nicht definiert, Was fürn Verhalten ist nicht definiert?
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.
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.