PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Spielerfehlschluss



robocat
05.10.2011, 17:18
Der Spielerfehlschluss ist ein logischer (http://de.wikipedia.org/wiki/Logik) Fehlschluss (http://de.wikipedia.org/wiki/Fehlschluss), dem die falsche Vorstellung zugrundeliegt, ein zufälliges (http://de.wikipedia.org/wiki/Zufall) Ereignis werde wahrscheinlicher, wenn es längere Zeit nicht eingetreten ist, oder unwahrscheinlicher, wenn es kürzlich/gehäuft eingetreten ist. [Q: Wikipedia / http://de.wikipedia.org/wiki/Spielerfehlschluss]

Um das zu demonstrieren, habe ich ein kleines C Programm geschrieben. Es wird ein Spiel simuliert, bei dem das eingesetzte Kapital verzehnfacht werden soll, zuerst ohne jede Strategie. Startkapital = 1 Münze, es wird dann weitergespielt (Münzwurf mit r=rand()%2), wobei immer 1 Münze gesetzt wird. Gelingt es im Lauf von beliebig vielen Spielen, 10 Münzen zu erreichen, gilt das Gesamtspiel als gewonnen.

int verloren=0,gewonnen=0,n=10000000;

for(int i=0;i<n;i++)
{

int kapital=1,spiele=0;

while(1)
{
spiele++;
int r=rand()%2;
if(r>0)kapital++;
else kapital--;
if(kapital==10)
{
//printf("Verzehnfacht nach %d Spielen.\n",spiele);

gewonnen++;
break;
}
else if(kapital==0)
{
//printf("Verloren nach %d Spielen.\n",spiele);
verloren++;
break;
}

}
}

printf("%d Spiele gewonnen, %d verloren.\n",gewonnen,verloren);
printf("Wahrscheinlichkeit zu gewinnen ist %lf\%\n",((float)gewonnen/(float)n)*100);



Wie man erwartet hätte, nähert sich die Wahrscheinlichkeit den 10%.

Nun dasselbe Spiel mal "mit Strategie". Und zwar wird eine Serie abgewartet, das heisst es wurde zB 5 Mal dasselbe Ergebnis geworfen, danach wird erst der Einsatz gemacht, und zwar auf das Ergebnis, das nun 5 Mal nicht eingetreten ist. Wenn es nach der Wiki geht, sollte da die Wahrscheinlichkeit ebenfalls 10% sein, denn die Münze hat ja kein Gedächtnis.

Ich komme mit meinem Programm aber auf eine höhere Gewinnwahrscheinlichkeit, weswegen ich denke, dass ich da irgendwo einen Fehler drin haben muss. Oder ist vielleicht der Zufalls-Algorithmus schlecht?


for(int i=0;i<n;i++)
{

int kapital=1,spiele=0;

int serie=0, last=-1, setnow=0;

while(1)
{
spiele++;

int r=rand()%2;

if(setnow)
{
serie=0;
setnow=0;
if(r==0)kapital++;
else kapital--;
}

if(r>0&&last>0)serie++;
else serie=0;

if(serie==4)setnow=1;

if(kapital==10)
{
//printf("Verzehnfacht nach %d Spielen.\n",spiele);

gewonnen++;
break;
}
else if(kapital==0)
{
//printf("Verloren nach %d Spielen.\n",spiele);
verloren++;
break;
}
last=r;
}
}
printf("mit system:\n");
printf("%d Spiele gewonnen, %d verloren.\n",gewonnen,verloren);
printf("Wahrscheinlichkeit zu gewinnen ist %lf\%\n",((float)gewonnen/(float)n)*100);

Der Zufallszahlengenerator wird übrigens vorher mit time() initialisiert:

#include <stdio.h>
#include <conio.h>
#include <stdlib.h> // random
#include <math.h>
#include <time.h>

int main()
{
time_t t;
time(&t);
srand((unsigned int)t);
......


Vielleicht sieht jemand meinen Fehler.

Liebe Gruesse von der Katze

danimath
06.10.2011, 09:40
Moin robocat,

ich habe mal Deine beiden Programme laufen lassen und bekomme bei beiden Werte um die 10% (mit gcc 4.1.2 - ich habe gerade keinen anderen;)). Einen logischen Fehler kann ich auch nicht entdecken. Das scheint also so OK zu sein. Hast Du mal 'ne Handvoll konkreter Werte? Wie hoch ist denn die höhere Wahrscheinlichkeit?

BTW: bei Simulationen ist es eher ungünstig den Zufallszahlengenerator mit der Zeit zu initialisieren - ein fester Wert ist da für Fehlersuchen besser geeignet (wegen der Reproduzierbarkeit); evtl als Kommandozeilenparameter. Wenigstens solltest Du den Startwert ausgeben.

viele Grüße
Andreas

oberallgeier
06.10.2011, 10:27
Ich hatte mal eine Würfelstatistik auf einem Taschenrechner programmiert. Die Zufallszahl war selbst geschrieben [ Nachkommazahl mit wählbarem Erstwert mal Pi - davon Nachkommawert - den mit sechs multipliziert plus eins - davon Integer abgeschnitten ergibt Würfelaugen; Pi ist die Konstante mit den meisten Nachkommastellen im Rechner]. Die Rechnung war double - der verwendete HP 42 rechnet intern, soweit ich weiß, mit etwa 18 Stellen, die auf double gerundet werden.

Die von mir errechnete Statistik schielte eindeutig. Ich hatte damals vermutet, dass jeder "Zufalls"algorithmus eben doch nur eine konkrete Rechenvorschrift ist, die ausgewählte Maxima und Minima hat. Da finde ich Deine zeitliche Zufallbasis doch gut. Aber den Grund für Deine Suche vermute ich trotzdem in der Zufälligkeit.

danimath
06.10.2011, 11:29
OK - ein bisschen offtopic: Zufallszahlen erzeugen ist nicht einfach: klick (http://www.softpanorama.org/Algorithms/random_generators.shtml) und klick (http://www.softpanorama.org/Algorithms/random_generators.shtml#FAQs).

viele Grüße und offtopic Ende
Andreas

robocat
06.10.2011, 13:52
Danke für eure Antworten, vor Allem auch danke an danimath für das Testen mit einem anderen Compiler (und für die lesenswerten Links). Ich benutze den alten Borland BCC32 Compiler, dessen Zufallsfunktion ich bisher für ANSI-C kompatibel hielt und deshalb darauf vertraut habe.

Bei 10 Millionen Spielen rechnet das Programmchen eine Weile und kommt dann auf völlig unglaubwürdige Ergebnisse (hier wurde "if(serie==3)setnow=1;" benutzt):
20217

Das ist auch, bis auf sehr wenige Ausnahmen, mit verschiedenen srand() Werten reproduzierbar.

Da ich auch grade keinen anderen C Compiler habe, werde ich vielleicht den Spass mal in php umsetzen. Vielleicht hat auch jemand von euch ein paar brauchbare Zufalls-Algorithmen.

Liebe Gruesse von der Katze

Richard
06.10.2011, 14:32
Vielleicht hat auch jemand von euch ein paar brauchbare Zufalls-Algorithmen.

Liebe Gruesse von der Katze

Nicht wirklich, aber so weit mir bekannt sind alle diese Zufalls Generatore nicht SO wirklich brauchbar. :-( So etwas sollte man aus "rosa Rauschen" ableiten.

Gruß Richard

robocat
06.10.2011, 17:34
Aus dem Link von danimath:

Knuth suggests various generators, including one that combines the first two table entries above:

xn+1 = 48271*xn mod (231 - 1),
yn+1 = 40692*yn mod (231 - 249),
zn = (xn - yn) mod (231 - 1),




Ok, diesen Generator habe ich nun mal verwendet

unsigned long lastrandom1,lastrandom2;

unsigned long random()
{
unsigned long z=(lastrandom1-lastrandom2)%2147483647; // 2^31-1
lastrandom1=(48271*lastrandom1)%2147483647;
lastrandom2=(40692*lastrandom2)%2147483399; // 2^31-249
return z;
}

// Seed:

time_t t;
time(&t);
srand((unsigned int)t);

lastrandom1=rand();
lastrandom2=rand();

Und sieheda, auch wenn der Generator nicht perfekt ist, lässt sich damit kein Vorteil beim Spiel "mit system" mehr feststellen.

PICture
06.10.2011, 17:44
Hallo!

So wie der Richard schrieb, fast perfekte Zufallsgeneratore lassen sich (wie in der Natur) nut Analog hardwaremässig realisieren. Besser und einfacher als "rosa" ist "weiss" Rauschen. Als Lekture würde ich das empfehlen: https://www.roboternetz.de/community/threads/47870-quot-perfektes-quot-wei%C3%9Fes-Rauschen ;)

danimath
06.10.2011, 17:55
Ok, diesen Generator habe ich nun mal verwendet


Ich wollt's noch vorschlagen ;) Eigentlich sind bei den aktuellen Pseudo-Zufallszahlengeneratoren nur die in der Art von D. Knuth verbreitet (in Java wird sogar explizit drauf verwiesen). Wer das Geld ausgeben möchte (oder eine gute Bibliothek in der Nähe hat), mag sich gern mal "The Art of Computer Programming" von D. Knuth zulegen (oder mal reinschauen). Neben Pseudozufallszahlen gibt es da auch so spannende Sachen wir Suchen Sortieren, Listen,... Man kann also viel über grundlegende Algorithmen lernen.

"Echte" Zufallszahlen sind - wie schon PICture und Richard geschrieben haben - nicht mit Algorithmen zu erzeugen. Das beste ist immer noch ein radioaktives Präparat mit einen Zähler; aber das bringt wieder andere Probleme ;););)

viele Grüße
Andreas

PICture
06.10.2011, 18:00
Wenn jemand Lust auf einfache Experimente hat, dann: https://www.roboternetz.de/community/threads/50619-Pseudozufallsgenerator-(gelöst) . ;)

Übrigens, ich werde sehr dankbar für Ausprobieren und Berichten. Am einfachsten wäre fehlerhaftes Unterprogramm für internen ADC Wandler., falls in dem µC vorhanden. :D

Richard
06.10.2011, 18:58
"Echte" Zufallszahlen sind - wie schon PICture und Richard geschrieben haben - nicht mit Algorithmen zu erzeugen. Das beste ist immer noch ein radioaktives Präparat mit einen Zähler; aber das bringt wieder andere Probleme ;););)

viele Grüße
Andreas

Hmm, ich (dachte) bisher das der Radioaktive Zerfall ein höchst zuverlässiges Signal erzeugt, weit entfernt von Zufall? Als (einigermaßen) guter Zufalls Generator, sollte ein Stück Draht mit offenen Ende an einen ADC Port taugen. Mit der Länge muss man etwas testen damit nicht gerade 50 Hz empfangen werden.

Gruß Richard

PICture
06.10.2011, 19:28
Wahrscheinlich meinst du, dass die max. zulässige für ADC Amplitude der empfangener Netzspannung nicht uberschritten wird. Ich würde deshalb an ADC Pin zwei Dioden anschliessen, falls es nicht intern geschützt ist (siehe Code). ;)

VCC
+
|
D1 -
lange "Antenne" ^
|
------------------------------------------------+---> ADC Pin
|
D2 -
^
|
===
GND

(created by AACircuit v1.28.6 beta 04/19/05 www.tech-chat.de)