zufallszahlen
-
~fricky schrieb:
pwr schrieb:
das ganze tritt bei der ursprünglichen lösung des OPs nicht auf, da in dem fall z1, z2 und z3 nicht abhängig voneinander sind.
aber er hat 'ne schleife drin, die unvorhersehbar oft rumeiert.
wie wär's mit sowas?int a = rand(); int b = rand(); int c = rand(); int div = (a+b+c)/34; a = a / div; b = b / div; c = c / div;
dürfte doch die anforderung erfüllen, dass die summe nicht grösser als 33 sein darf, oder?
Ich würde dem jetzt auf die Schnelle mal wiedersprechen, da bei einem kurzen Test zu hohe Durchschnittswerte (10,xx) raus kamen.
-
Korhil schrieb:
Ich würde dem jetzt auf die Schnelle mal wiedersprechen, da bei einem kurzen Test zu hohe Durchschnittswerte (10,xx) raus kamen.
den kannst du ja zurechtbiegen, z.b. indem du den drei 'rands' wieder ein mod(irgendwas) verpasst. (und dafür sorgst, dass 'div' nicht 0 wird).
-
Hallo Leute,
sorry, wegen Zeitmangels erst jetzt Rückmeldung. Also, ich hab's eingesehen, daß helihjbs "Lösung" eine unzulässige Verteilung herbeiführt, weil die Würfe eben nicht mehr unabhängig sind.
Ich hab' jetzt ein wenig herumgebosselt und das da fabriziert:#include <stdlib.h> #include <math.h> int main(void); const unsigned long int wuerfe = 1000000; #define N 33 #define N1 34 int random (int max) { return rand() / (RAND_MAX / max + 1); // [0... max] } int main(void) { unsigned int summe, rest, z1, z2, z3, i; double abweichung; unsigned long int geworfen,a,b; unsigned long int heli[N1]; unsigned long int marge[N1]; unsigned long int imarge[N1]; unsigned long int sum_heli = 0; unsigned long int sum_marge = 0; unsigned long int sum_imarge = 0; for (i = 0; i<(N1); i++) { heli[i] = 0; marge[i] = 0; imarge[i] = 0; } srand(12); // Heli- Section printf("Running Heli\n"); srand(12); geworfen = 0; do { rest = N; z1 = random(rest); heli[z1]++; rest -= z1; z2 = random(rest); heli[z2]++; rest -= z2; z3 = random(rest); heli[z3]++; geworfen++; } while (geworfen < wuerfe); // marge- Section printf("Running marge\n"); srand(12); geworfen = 0; do { do { z1 = random(N); z2 = random(N); z3 = random(N); summe = z1 + z2 +z3; } while (summe > N); marge[z1]++; marge[z2]++; marge[z3]++; geworfen++; } while (geworfen < wuerfe); // improved marge- Section printf("Running improved marge\n"); srand(12); geworfen = 0; z1 = random(N); z2 = random(N); do { /* z1 = random(N); // z2 = random(N); do { z2 = z1; z1 = random(N); summe = z1 + z2; } while (summe > N); */ do { z3 = z2; z2 = z1; z1 = random(N); // z1 = random(N); // z2 = random(N); // z3 = random(N); summe = z1 + z2 + z3; } while (summe > N); imarge[z1]++; imarge[z2]++; imarge[z3]++; geworfen++; // z1 = random(N); // z2 = random(N); } while (geworfen < wuerfe); // Auswertung // Kontrolle: Wurffehler vermeiden for (i = 0; i<(N1); i++) { sum_heli += heli[i]; sum_marge += marge[i]; sum_imarge += imarge[i]; } printf("%u heli \n", sum_heli); printf("%u marge \n", sum_marge); printf("%u imarge \n", sum_imarge); // Abweichungen in % ermitteln for (i = 0; i<(N1); i++) { a = marge[i]; b = heli[i]; abweichung = (double)b - (double)a; abweichung = 100.0/(double)marge[i] * abweichung; printf("Bei %u heli zu marge %f%%,", i, abweichung); b = imarge[i]; abweichung = (double)b - (double)a; abweichung = 100.0/(double)marge[i] * abweichung; printf(" imarge zu marge %f%% \n", abweichung); } return 0; }
Stört euch nicht an unnötigen Deklarationen, ist nur, damit man im Debugger bequem Watches anlegen kann.
Was mir an Helis Lösung gefallen hat, war, daß man nichts verwirft, das hat mich wohl betriebsblind gemacht.
Ich habe das (Nicht-) Verwerfen zu optimieren versucht und die imarge- Methode entworfen, zunächst indem ich den dritten Wurf erst gar nicht ausgeführt habe, wenn man schon über 33 ist und nachfolgend den dritten Wurf nachgeschoben habe, bis das Ergebnis paßt.Aber jetzt wird's strange:
- ich habe srand jeweils mit einer seed von 12 gesetzt, damit ich immer den gleichen "Zufall" habe. Nur, wenn ich den imarge- Block durch die astreine marge- Methode ersetze, weichen die Ergebnisse immer noch voneinander ab. Dürfte doch eigentlich nicht sein, oder?
- Daß Heli einfährt, ist unbestreitbar, aber mit nach zwei Würfen Nachschauen (Summe kontrollieren) und neu beginnen habe ich auch Schiffbruch erlitten. Um die 11% Abweichung für die Null war die Folge.
- Rein jeweils einen Wert nachschieben, so, wie es jetzt dasteht, führt zu gleichen Ergebnissen wie zwei marge- Blöcke, ABER wenn ich die vorherigen Würfe NICHT verwerfe (Kommentierung Z. 113/114 aufheben), um neue Würfe zu laden, ergibt sich das gleiche Bild, wie nach zwei Würfen ggf. zu verwerfen.Kann das jemand erklären? Für heute bin ich zu müde, frickys Methode zu testen, dürfte aber eigentlich probat sein.
Noch was: Ich habe jetzt Pelles C als q&d- Fab getestet, diesen Code frißt es aber nicht, wurde stattdessen mit dem Watcom und einem embedded Compiler getestet. Pelle stört sich daran, daß beim Linken z.B. _rand als externes Symbol nicht aufgelöst werden konnte. Weiß jemand wass dazu?
-
frickys ansatz sieht recht nett aus, jedoch haben die zahlen immer eine summe von 33, die aufgabe war jedoch kleiner (gleich?) 33
dann is da noch das problem mit dem abrunden bei integer divisionen.
ich würde folgendes machen:int sum = rand()%34; //34 oder 33) int a = rand(); int b = rand(); int c = rand(); float div = ((float)(a+b+c))/sum; a = (int)(0.5 + a / div); b = (int)(0.5 + b / div); c = (int)(0.5 + c / div);
-
vlad_tepesch schrieb:
frickys ansatz sieht recht nett aus, jedoch haben die zahlen immer eine summe von 33, die aufgabe war jedoch kleiner (gleich?) 33
... ich würde folgendes machen:int sum = rand()%34; //34 oder 33) int a = rand(); int b = rand(); int c = rand(); float div = ((float)(a+b+c))/sum; a = (int)(0.5 + a / div); b = (int)(0.5 + b / div); c = (int)(0.5 + c / div);
Jetzt bist Du ins gleiche Messer gelaufen wie ich. Die Summen sind nicht gleichmäßig verteilt, man darf sich eben nicht auf einer gleichmäßigen Verteilung basierend die vorherigen Ereignisse zurechtschnitzen.
Und leider auch nicht auf die Zielsumme zusammenhämmern, das gilt für frickys Lösung genauso.
Schaut euch nochmal das da an:srand(12); geworfen = 0; z1 = random(N); z2 = random(N); do { do { z3 = z2; z2 = z1; z1 = random(N); summe = z1 + z2 + z3; } while (summe > N); imarge[z1]++; imarge[z2]++; imarge[z3]++; geworfen++; // z1 = random(N); // z2 = random(N); } while (geworfen < wuerfe);
Die Verteilung ist genauso wie bei der richtigen Ur- Lösung. Nachteil ist, daß dabei Zahlen aus einem gültigen 3er- Wurf im nächsten weiterverwendet werden. Auf den Zeilen 21/22 habe ich z1 und z2 daher neu angelegt. Lustigerweise ändert sich dann aber die Verteilung für ein paar Zahlen über 10% gegenüber der richtigen Lösung.
Das verstehe ich nicht.
-
pointercrash() schrieb:
man darf sich eben nicht auf einer gleichmäßigen Verteilung basierend die vorherigen Ereignisse zurechtschnitzen.
Und leider auch nicht auf die Zielsumme zusammenhämmernaber wie willste es sonst machen? die 'zufallswerte' sind wegen dieser forderung, dass alle zusammen nicht grösser als 34 sein dürfen, immer irgendwie voneinander abhängig. also kann man da nix berechnen, ohne die summe zu beachten. es bleibt also nur das rumprobieren in einer schleife (der code des OP, alles andere hier ist mist). naja, ich persönlich finde schleifen und 'floats' doof für sowas. aber anscheinend geht's nicht besser, oder?
-
~fricky schrieb:
... naja, ich persönlich finde schleifen und 'floats' doof für sowas. aber anscheinend geht's nicht besser, oder?
Mich hat das viele Weggeschmeiße gestört, das Float- Zeugs sowieso. Bei einmal ist es egal, aber wenn man mal 10 Mio mal würfelt, dauert das doch.
Aber hast Du meinen letzten Codeschnipsel angesehen? Der liefert die gleiche Verteilung ab, wie der Code des OP und ist deutlich schneller. Komischerweise driftet aber die Verteilung weg, wenn man nach einem erfolgreichen Wurf z1 und z2 neu besetzt.
-
pointercrash() schrieb:
Aber hast Du meinen letzten Codeschnipsel angesehen? Der liefert die gleiche Verteilung ab, wie der Code des OP und ist deutlich schneller.
klar, du rufst pro schleifendurchlauf nur einmal rand auf, während der OP immer alle 3 werte neu erzeugen lässt. ist 'ne optimierung, aber eigentlich das gleiche, nämlich rumprobieren in einer schleife
pointercrash() schrieb:
Komischerweise driftet aber die Verteilung weg, wenn man nach einem erfolgreichen Wurf z1 und z2 neu besetzt.
finde ich auch seltsam...
-
@pointercrash ein anderes Problem bei dir ist, das du im 2. wurf immer die zahlen des voherigen mitbenutzt.
so wärs richtiger:
for(int i=0; i< wuerfe; ++i) { at = random(N); bt = random(N); ct = random(N); while (at+bt+ct > N) { ct = bt; bt = at; at = random(N); } }
Is aber auch nicht gleichverteilt, wie übrigens marges erster ansatz auch nicht!
Ich habe aber die Lösung:
at = random(6); bt = random(6); ct = random(6);
Die summe (a+b+c) ist kleiner 33 und die zahlen a, b und c sind gleichverteilt!
Es ist nicht möglich eine gleichverteilung zu erreichen, wenn jede zahl im Bereich 0-33 liegt. das ist, als wenn man mit 2 würfeln würfelt und bei summe > 6 neu würfelt.
da werden die niedrigeren Würfelaugen öfter liegen bleiben
-
vlad_tepesch schrieb:
@pointercrash ein anderes Problem bei dir ist, das du im 2. wurf immer die zahlen des voherigen mitbenutzt.
so wärs richtiger:
for(int i=0; i< wuerfe; ++i) { at = random(N); bt = random(N); ct = random(N); while (at+bt+ct > N) { ct = bt; bt = at; at = random(N); } }
Is aber auch nicht gleichverteilt, wie übrigens marges erster ansatz auch nicht!
Ich habe aber die Lösung:
at = random(6); bt = random(6); ct = random(6);
Die summe (a+b+c) ist kleiner 33 und die zahlen a, b und c sind gleichverteilt!
Es ist nicht möglich eine gleichverteilung zu erreichen, wenn jede zahl im Bereich 0-33 liegt. das ist, als wenn man mit 2 würfeln würfelt und bei zahlen > 6 neu würfelt.
da werden die niedrigeren Würfelaugen öfter liegen bleibenDu mußt dich - denke ich - von der klassischen Normalverteilung gedanklich verabschieden. Hier liegt ein anderes Problem vor, so dass die Normalverteilung hier halt anders aussieht. Trotzdem gibt es die Normalverteilung zu diesem Problem.
-
wer will denn eine Normalverteilung?
eine gleichverteilung war das ziel!
-
hat nicht mal einer von euch lust, was mit logikoperatoren zu machen. 33 ist ja immerhin ganz nah an 2^5. vielleicht geht da was.
-
vlad_tepesch schrieb:
wer will denn eine Normalverteilung?
eine gleichverteilung war das ziel!Da hab ich wohl zu viel gedacht und zu wenig gelesen.
Naja, so herum macht das ganze nur wirklich wenig Sinn, da große Zahlen häufiger abgelehnt werden, kommt es nie zu einer Gleichverteilung.
@marge Meintest du wirklich Gleichverteilung ?
-
Korhil schrieb:
Da hab ich wohl zu viel gedacht und zu wenig gelesen.
Geht nicht nur Dir so
Korhil schrieb:
Naja, so herum macht das ganze nur wirklich wenig Sinn, da große Zahlen häufiger abgelehnt werden, kommt es nie zu einer Gleichverteilung.
Ja, aber keine Selbstzerwürfnisse deswegen:
marge schrieb:
Ich möchte drei Zufallszahlen erzeugen, deren Summe nicht größer als 33 ist. Die Zahlen sollen gleich wahrscheinlich sein.
Man kann das eigentlich nur so sinnvoll lesen, daß die Eingangsereignisse unabhängig voneinander gewonnen werden und bei der Auswertung geschaut wird, ob der Wurf gültig war. Wenn nicht, wird neu gewürfelt.
Damit ist der OP- Code aufgabenkonform, da die Aufgabe ja nicht die Gleichverteilung der Summen vorschreibt, die häufeln sich natürlich im oberen Bereich, während die einzelnen Zahlen unten rum sehr wahrscheinlich sind und nach oben hin wegbrechen.
Müßte mein Code eigentlich auch machen, aber die Mitbenutzung vorheriger Ergebnisse ist ja eigentlich unkoscher. Warum die Neuinitialisierung von z1 und z2 die Sache verschlimmbessert, ist das eigentliche Rätsel.
-
der OP code entspricht nicht den Anforderungen!
größere Zahlen werden häufiger neu ausgewürfelt.
das heist das niedrigere Zahlen öfter liegen bleiben.Beispiel 2 Würfel:
maximale zahl 6, summe soll <=7 werden (sieben, weil die wüfel von 1..6 und nnicht von 0..6 haben).
jeder Würfel für sich hat die ereignisse
1 2 3 4 5 6folgende kombinationen sind also möglich:
1 2 3 4 5 6 ------------------ 1| 2 3 4 5 6 7 2| 3 4 5 6 7 8 3| 4 5 6 7 8 9 4| 5 6 7 8 9 10 5| 6 7 8 9 10 11 6| 7 8 9 10 11 12
soll die summe <= 7 sein bleibne folgende übrig:
1 2 3 4 5 6 ------------------ 1| 2 3 4 5 6 7 2| 3 4 5 6 7 3| 4 5 6 7 4| 5 6 7 5| 6 7 6| 7
das sind also alle möglichen Kombinationen (bei allen anderen wird ja neu gewürfelt)
wie man sieht, gibt es für die 6 nur zwei Kombinationen in denen die 6 vorkommen kann, wohihngegen die 1 in 11 kombinationen vorkommen kann.
Das heist bei einem solchen experiment gibt es keine möglkichkeit eine gleichverteilung hinzubekommen.
Für die Summe ist das sowiso nicht möglich da die addition zweier gleichverteilter Zufallsvariablen eine normalverteilte entsteht.
-
vlad_tepesch schrieb:
wie man sieht, gibt es für die 6 nur zwei Kombinationen in denen die 6 vorkommen kann, wohihngegen die 1 in 11 kombinationen vorkommen kann.
Das heist bei einem solchen experiment gibt es keine möglkichkeit eine gleichverteilung hinzubekommen.
Für die Summe ist das sowiso nicht möglich da die addition zweier gleichverteilter Zufallsvariablen eine normalverteilte entsteht.