Hallo (komme von der Pascal Ecke) wie kann man mit C die Zufallszahlen 1 - 6 Würfel erzeugen. srand(toc); int lol = rand(); char zahl = lol; zahl = zahl & 0b00000111; So hatte ich mir das gedacht macht nur dummerweise Zz. von 0 - 7
Martin Michael schrieb: > So hatte ich mir das gedacht macht nur dummerweise > Zz. von 0 - 7 Wenn du den Rest einer Division willst, dann schreib auch Rest. Das ist der % Operator und nicht eine Verundung &. Wenn man das bei bestimmten Zahlen und Datentypen optimieren kann (zb bei 7, 15, 31, etc. und unsigned Werten), dann ist dein Compiler schon clever genug, die Modulo Operation gegen eine Verundung auszutauschen. Das macht dem Compiler gar nichts aus. Compiler beherrschen sowas seit mehr als 40 Jahren. Angeblich gab es mal einen Compiler der das nicht konnte - irgendwann in grauer Vorzeit, die Menschheit war copmutertechnisch gerade von den Bäumen runtergekommen (sozusagen), das muss so um 1965 rum gewesen sein - aber dieses Gerücht konnte nie richtig bestätigt werden.
:
Bearbeitet durch User
Ist es nicht so, daß eine Random-Funktion in C einen Float-Wert zwischen 0 und 1 zurück gibt? Den multipliziert man mit 5, und addiert 1 dazu. In C verwendete ich sowas noch nicht, zumindest an µC, aber machte da Zufallszahlen in Assembler auch für Würfelspiele. Man kann aber auch mal einen Blick in die Compiler-Libraries werfen, wie die Zahl erzeugt wird. Bei meinem SDCC-Compiler für 8051 stehen dort zwei komische Konstanten drin, die als Ausgangszahl verwendet werden.
Wilhelm F. schrieb: > Ist es nicht so, daß eine Random-Funktion in C einen Float-Wert zwischen > 0 und 1 zurück gibt? Nein. rand liefert einen int Einige Bibliotheken haben eine Erweiterung, die dann meistens random() heißt. Ist aber im Grunde auch nichts anderes als
1 | rand() / (double)RAND_MAX |
die Floating Point Division kann man sich daher auch sparen, wenn man sowieso nur an ganzen Zahlen interessiert ist.
:
Bearbeitet durch User
Modulo: zahl = (zahl % 6 ) + 1; danke dafür Wilhelm F so macht es Delphi Pascal. c gibt nach help einen halben 0xffff als integer also 0x7fff oder 32767 dezimal
Wird mit Modulo 6 nicht die Gleichverteilung der Ergebnisse beeinflusst? Weil 2^8 / 6 = 42 Rest 4, d.h. die ersten vier Zahlen kommen häufiger vor also die restlichen. Oder ist das ein Denkfehler meinerseits?
muup schrieb: > Wird mit Modulo 6 nicht die Gleichverteilung der Ergebnisse beeinflusst? Ja. Man kann das Problem umgehen, indem man die Größe des genutzten Wertebereichs des Zufallszahlengenerator auf die nächstkleinere durch 6 teilbare Zahl einschränkt. Der Zufallszahlengenerators wird einfach so lange wiederholt aufgerufen, bis die Zahl in diesem eingeschränkten Wertebereich liegt. Dann wird der Sechserrest gebildet, und die Ergebnisse sind perfekt gleichverteilt.
Yalu X. schrieb: > Dann wird der Sechserrest gebildet, und die > Ergebnisse sind perfekt gleichverteilt. Richtig, aber wenn Du Pech hast, wird es eine Endlosschleife ;-) Man könnte auch so viele Zufallszahlen addieren, dass sich ein exaktes Vielfaches des Zielbereichs ergibt. Und dann wieder die Modulo-Operation und + 1
Eine bessere Alternative wäre wohl: [rand() + rand() + rand()] mod 6 + 1 weil 3*2^8 / 6 = 128 Rest 0 deterministische Ausführung Viele Grüße!
Oder noch besser: [rand() / 4 + rand () / 4 + rand() / 4] mod 6 + 1 dann kann man mit uint8 rechnen und muss nicht erst über uint16 beim Addieren gehen.
Eddy Current schrieb: > Richtig, aber wenn Du Pech hast, wird es eine Endlosschleife ;-) Theoretisch ja. Praktisch: Wir sind hier im PC-Forum, auf 32-Bit-PCs ist RAND_MAX typischerweise 2**31-1, die rand-Funktion liefert also 2**31 unterschiedliche Werte. Da 2**31 ≡ 2 (mod 6), muss in 2 von 2**31 Fällen ein zweiter Wert, in 4 von (2**31)**2 ein dritter Wert und in 8 von (2**31)**3 ein vierter Wert generiert werden. Angenommen du möchtest den PC jede Nanosekunde würfeln lassen (dazu muss der PC schon ziemlich flott sein). Dann werden nach dem obigen Verfahren im Mittel nur alle 40 Milliarden Jahre mehr als 3 rand-Aufrufe pro Wurf benötigt. Man kann deswegen die Anzahl der Schleifendurchläufe guten Gewissens auf 3 begrenzen. > Man könnte auch so viele Zufallszahlen addieren, dass sich ein exaktes > Vielfaches des Zielbereichs ergibt. Und dann wieder die > Modulo-Operation und + 1 Das geht nicht, da die Summe mehrerer gleichverteilter Zufallszahlen nicht mehr gleichverteilt ist, und zwar nicht einmal näherungsweise.
Yalu X. schrieb: > Dann werden nach dem obigen Verfahren > im Mittel nur alle 40 Milliarden Jahre mehr als 3 rand-Aufrufe pro Wurf > benötigt. Sag ich doch. Endlosschleife. Mit ein "wenig" Pech. Wobei Dein beschriebenes Verfahren schon recht effektiv arbeitet. Sprich: Neuwürfeln, wenn der Wert des Zufallsgenerators jenseits des höchsten Vielfachen der Modulooperation und dem Ende des Wertebereichs des Zufallsgenerators liegt. Yalu X. schrieb: > Das geht nicht, da die Summe mehrerer gleichverteilter Zufallszahlen > nicht mehr gleichverteilt ist, und zwar nicht einmal näherungsweise. Interessant. Nach ein wenig Nachdenken stimme ich Dir voll und ganz zu! Alleine die Betrachtung der Wahrscheinlichkeit für den Wert 0 als summiertes Zufallsergebnis im Vergleich zu 1 beweist schon, dass da ein Schieflage sein muss. Es sieht nach einer höheren Wahrscheinlichkeit für Zahlen im mittleren Wertebereich aus, weil hier mehr Kombinationen zum Zielwert führen. Welche Verteilung konkret herauskommt, kann ich aber auf die Schnelle auch nicht sagen. Danke für's Augenöffnen.
Martin Michael schrieb: > Wilhelm F so macht es Delphi Pascal. > > c gibt nach help einen halben 0xffff als integer > also 0x7fff oder 32767 dezimal Danke. Sorry, ich lag da etwas falsch, aber mein Taschenrechner HP48G macht es so, gibt einen Float-Wert zwischen 0 und 1 zurück. Damit kann man auf jeden Fall was anfangen. Bei meinem SDCC-Compiler schaute ich mal in rand.c hinein. Es stehen dort zwei Float-Konstanten drin, die mit irgendwas verwurstelt werden, das muß ich noch mal weiter verfolgen. Selbstverständlich wird dort aber ein long-Wert zurück gegeben. Es kann sein, daß ein System-Timer des 8051 dafür betrieben werden muß, im bestimmten Mode, weiß ich auch noch nicht exakt genau. In Assembler machte ich auch schon mal Zufallszahlen für ein Würfelspiel, verwendete dort z.B. auch einen 32-bit-Rauschgenerator mit, bei dem bit 15 und bit 31 über XOR auf den Input zurück gekoppelt sind, und ein paar andere Dinge wie z.B. den Timerwert und einen endlos mit laufenden Timer-Tick mit der Laufzeit in ms. Ich hab da einfach mal nur ein wenig probiert, verschiedene Dinge da miteinander zu vermengen, verrechnen, wie ein neues Essensrezept aus einem Wochen-Werbeblatt, bin ja kein Mathematik-Wissenschaftler. Da habe ich oft auch den Eindruck, daß Rezepte per Zufallsgenerator zusammen gemengt werden. Die Werte wurden getestet, hab von der Software generierte Zahlenreihen in Excel hinein geladen, und statistisch ausgewertet. Dafür ist Excel (oder OpenOffice Calc) schon gut genug. Die Verteilung war ausgezeichnet, mehr will man ja nicht. Wenn ich noch mal an ein industrielles Erzeugnis heran gesetzt würde, da würde ich natürlich durchaus auch nach professionelleren Algorithmen, Methoden und Auswertung suchen.
Yalu X. schrieb: > Theoretisch ja. Praktisch: > > Wir sind hier im PC-Forum, auf 32-Bit-PCs ist RAND_MAX typischerweise > 2**31-1, die rand-Funktion liefert also 2**31 unterschiedliche Werte. Da > 2**31 ≡ 2 (mod 6), muss in 2 von 2**31 Fällen ein zweiter Wert, in 4 von > (2**31)**2 ein dritter Wert und in 8 von (2**31)**3 ein vierter Wert > generiert werden. > > Angenommen du möchtest den PC jede Nanosekunde würfeln lassen (dazu muss > der PC schon ziemlich flott sein). Dann werden nach dem obigen Verfahren > im Mittel nur alle 40 Milliarden Jahre mehr als 3 rand-Aufrufe pro Wurf > benötigt. Man kann deswegen die Anzahl der Schleifendurchläufe guten > Gewissens auf 3 begrenzen. Praktisch verbirgt sich hinter rand() eh nur ein Pseudozufallsgenerator mit in dem Fall maximaler Periodenlänge 2**32. D.h. nach vier Milliarden abgerufenen Zufallszahlen treten wieder exakt die gleichen Zahlen in der gleichen Reihenfolge auf. Im Worst-Case kommen die vier unerwünschten Werte jedes Mal hintereinander vor, danach kommt dann aber garantiert ein anderer ... :)
Eddy Current schrieb: > Es sieht nach einer höheren Wahrscheinlichkeit für Zahlen im mittleren > Wertebereich aus, weil hier mehr Kombinationen zum Zielwert führen. > Welche Verteilung konkret herauskommt, kann ich aber auf die Schnelle > auch nicht sagen. http://de.wikipedia.org/wiki/Zentraler_Grenzwertsatz
MMMh wow, so viel zum Thema Würfeln. Yalu das stimmt nicht, rein Theoretisch kann es passieren....... Man nehme eine nicht mögliche abstrakte infinity Schleife und Würfelst, da kann es passieren das Du 100 mal hintereinander sechs würfelst und wenn danach gefragt wird wie groß ist die chanche als nächstes eine sechs zu würfen. 1:6. Ist aber rein Theortisch also irgend wie wenn man das wie mit Primzahlen mit einen super duper Computer .......
Ich mag mich irren, aber da die Periodenlänge von rand() typischerweise bei 2*32 liegt, ist das ganze doch gleichbedeutend mit der Frage: gibt es in so einer Periode eine Folge von 4 oder mehr Zahlen, auf die die Eigenschaft "größer als RAND_MAX - 2" zutrifft. Wenn nicht, dann ist die ganze Fragestellung für diesen konkreten Generator sowieso hinfällig. Praktisch gesehen. Praktisch gesehen ist auch rand() % 6 für den Hausgebrauch gut genug. Bei einer professionellen Glücksspiel-Programmierung sieht das natürlich anders aus. Aber zur Würfel-Simulation beim Mensch-ärgere-dich-nicht reicht es allemal. Die Profis hingegen benutzen ganz sicher nicht rand() :-)
:
Bearbeitet durch User
Martin Michael schrieb: > wie kann man mit C die Zufallszahlen 1 - 6 Würfel erzeugen. Nimm 4 :-) http://xkcd.com/221/
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.