Einzelnen Beitrag anzeigen

Benutzerbild von Nikolas
Nikolas

Registriert seit: 28. Jul 2003
1.528 Beiträge
 
Delphi 2005 Personal
 
#17

Re: Mehr Speed für Random?

  Alt 24. Jul 2007, 10:43
Das zählen der sechser ist auch kein Problem, das kann mit dem gleichen Code sauber gelöst werden.
Das mit den Arrays musst du dir selber mal anschauen, da gibts so viele Quellen zu, das sollte wirklich kein Problem darstellen.
Die Idee ist eigentlich recht einfach. Sagen wir mal, du hast 3 Würfel und musst eine Drei Würfeln. p(0) gibt dann an, wie wahrscheinlich es ist, nur einser und zweier zu würfeln, also 0 Treffer zu machen. Die Wahrscheinlichkeit liegt dafür bei p(0)=(2/6)^3.
Die andeneren Wahrscheinlichkeiten p(1) bis p(3) kannst du über die oben beschriebene Gleichung für die Binomialverteilung berechnen. (Im weiteren gehe ich mal von nur drei Würfeln aus)
also p(0)=8/27, p(1)=(2/6)^2*(4/6)*3=4/36*2=8/36 (die drei kommt aus dem Binomialkoeffizienten), usw.
Während du dir diese Werte ausrechnest, legst du eine Liste an:
Der erste Eintrag ist p(0), der zweite ist p(0)+p(1), der dritte p(0)+p(1)+p(2), der dritte dann p(0)+p(1)+p(2)+p(3), wobei du den nicht ausrechnen musst, da er 1 ist. (gute Kontrollmöglichkeit, ob du vorher richtig gerechnet hast).
Das ist jetzt sozusagen deine Einteilung für dein Glücksrad. Wenn alle Wahrscheinlichkeiten bei 1/3 gelegen hätten, lägen deine Einträge bei 1/3, 2/3, 3/3=1. Die Abstände zwischen zwei benachbarten Zahlen ist dann ein Maß dafür, wie wahrscheinlich es ist, dieses Ergebniss zu erhalten.
Bei unserem Beispiel oben sind die ersten beiden Felder grob gleich groß, das nächste wird deutlich größer, da zwei Treffer hier der wahrscheinlichste Ausgang sind.
Jetzt machst du einen Randomaufruf und erhällst eine Zahl zwischen Null und eins. Jetzt musst du nur noch herrausfinden, in welchem Abschnitt diese Zahl ist. Dafür gehst du die p-Liste Schritt für Schritt durch und schaust, ob der jeweilige Wert größer ist, als die gezogene Zahl. Sobald das der Fall ist, bist du fertig. Wenn z.B. die Zahl 6/27 aus dem Generator gekommen ist, bist du sofort fertig, da p(0)>6/27, und du gibst als Ergebniss die 0 Treffer zurück, gibt der Generator aber 9/27 raus, fliegst du erst bei der zweiten Überprüfung raus, gibst also 1 Treffer zurück. Damit hast du pro Wurf (egal, wie viele Würfel zu benutzt, es können auch gerne 50 sein), nur einen einzigen Randomaufruf und ein paar Vergleiche.

Bis jetzt bin ich von einer bestimmten Anzahl an Würfeln und einer bestimmten Zahl die überboten werden muss, ausgegangen und habe dafür die Liste der Wahrscheinlichkeiten angelegt. Dieses zweidimensionale Array, von dem ich im letzten Post erzählt habe, ist also eigentlich nichts anderes als eine Art Buch, in dem die Wahrscheinlichkeitslisten abgedruckt sind. Wenn also eine Anfrage für 23 Würfel kommt, die die 5 Überbieten müssen, suchst du dir einfach die passende Tabelle raus und machst dann wie oben weiter.


// Ab jetzt wirds noch etwas Spielerei, das brauchst du eigentlich noch nicht.
Die Anzahl der Vergleiche ist hier offensichtlich der Schritt der die meiste Zeit während der eigentlichen Berechnung benötigt, nachdem die Liste zu Programmstart aufgestellt wurde. Die Frage ist jetzt, wie viele dieser Vergleiche benötigt werden. (Ich gehe jetzt mal von 10 Würfeln aus)
Wenn du die Liste einfach so vom Anfang an durchgehst, wirst du zu viele Vergleiche mit den Wahrscheinlichkeiten von p(0) p(1) usw vergeuden, da diese nur recht selten wirklich auftreten. Die Frage ist jetzt also, wo du am Besten mit der Suche anfängst, und in welcher Reihenfolge du die Werte anschaust. Meine Idee sieht so aus: (nicht ganz perfekt durchdacht, sollte aber recht gut sein)
Du beginnst beim Erwartungswert. (Der Erwartungswert ist die Anzahl an treffenden Würfeln, die auf lange Sicht am Häufigsten auftauchen. Bei 10 Würfeln und einem Minimum von 4 werden das sicherlich 5 sein, bei einem Minimum von 1 auf jeden Fall 10. Mit etwas denken oder Wikipedia, kommt man drauf, dass der Erwartungswert bei N*p liegt, wobei N die Anzahl der Würfel (z.B. 10) und p die Wahrscheinlichkeit, dass ein bestimmter einzelner Würfel trifft. (wenn du eine sechs würfeln musst, liegt p dann bei 1/6 und der Erwartungswert für 6 Würfel bei 1, d.h. wenn du sechs Würfel wirfst, wirst du meistens eine sechs sehen, was intuitiv auch klar sein wird)
Du vergleichst also deine Zufallszahl aus dem Generator (x) mit p(EW). Für x>EW vergleichst du sie mit p(EW+1) und dann nach oben, für x<p(EW) mit den darunterliegenden.
Das dürfte in den meisten Fällen sehr schnell zum Ergebniss führen.
{Wenn hier noch ein paar InfoStudenten mitlesen: Kennt ihr da einen SuchAlgo, der auf die Binomialverteilung oder andere Verteilungen optimiert wurde? Vll so eine Mischung aus meiner Startwertbestimmung mit einer binären Suche? Zu zeigen, dass ein Suchalgo minimale laufzeit für diese Binomialwerte hat, wäre doch sicher eine schöne Zettelaufgabe

Die OH ist nicht die CodeLibrary. In zweiteres kommen Codestücke, die so schön oder hilfreich sind, dass sie hier anderen Schreibern zur Verfügung gestellt werden. Die OH ist die in Delphi integrierte Hilfe, einfach mal F1 drücken und los gehts.
Erwarte das Beste und bereite dich auf das Schlimmste vor.
  Mit Zitat antworten Zitat