Du må være registrert og logget inn for å kunne legge ut innlegg på freak.no
X
LOGG INN
... eller du kan registrere deg nå
Dette nettstedet er avhengig av annonseinntekter for å holde driften og videre utvikling igang. Vi liker ikke reklame heller, men alternativene er ikke mange. Vær snill å vurder å slå av annonseblokkering, eller å abonnere på en reklamefri utgave av nettstedet.
  16 1858
Jeg prøver å lage et program som simulerer en roulette. Målet med programmet er å estimere sannsynligheten for å tape X antall ganger på rad i løpet av N antall spins på rouletten.

Problemet mitt er at i følge wikipedia, overestimerer programmet mitt denne sannsynligheten med et par prosent.
For 73 spinns skal det være 50,3 % sjanse for å tape 6 ganger på rad minst en gang. Min kode gir rundt 52,3%.
Programmet mitt ligger generelt 2-4% (ikke prosentpoeng) over det som er forventet ut i fra eksemplene på wikipedia.
Har kjørt en del millioner spins, og får konsistent ut denne overestimeringen.

Merk: koden bærer preg av noen timer med prøving og knoting så den er litt rotete.

Kode

def main():
    import random

    N = eval(input("Angi hvor mange spins som skal utføres i hver runde: "))
    X = eval(input("Angi hvor mange tap på rad som definerer \"suksess\": "))
    R = eval(input("Angi hvor mange ganger prosessen skal gjentas: "))
    print()

    #Vinnertall 21 22 23 24 25 26 27 28 29 30 21 32 33 34 35 36 37 38
    #Tapertall  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 16 17 18 19 20  


    suksess = 0
    res = 0
    delsuksess = 0
    vinn =0
    spins = 0
    runder = 0


    for i in range(R):                  #Ytre løkke, hvor mange ganger skal runden simuleres
        runder += 1
        delsuksess = 0
        
       
        for j in range(N):               #Indre løkke, hvor mange spins i hver runde
            spins += 1

            res = random.randint(1,38)  #Generer tilfeldig tall fra 0 til 37
            
            if res >= (21):             #Sjansen for å vinne er 18/38,for å tape 20/38, vinn definerers derfor som et tall større enn 20 (21-38)
                delsuksess = 0          #Hvis runden er en vinnerrunde settes delsuksess til null
                vinn += 1
                

            if res <= 20:
                delsuksess = delsuksess + 1       #Hvis runden er en taperrunde legges 1 til delsuksess

            if delsuksess >= X:                   #Hvis man har fått 6 tap på rad defineres dette som suksess og løkken avbrytes
                suksess += 1
                delsuksess = 0
                break            
     
    print("Vinnere", vinn, "antall totale spins" ,spins, round(((vinn*100)/spins),3),"%" )
    print()
    print("suksesser(tap", X, "ganger på rad):" , suksess)
    print("Repetisjoner av prosessen ", runder)
    print("I løpet av", N, "spins er det" ,round((suksess*100)/runder,3),"%","sannsynlig å tape", X, "ganger på rad minst en gang")


Jeg har følgende hypoteser for hva som kan være feilen:

1. Koden min teller i noen tilfeller to suksesser på en runde.
2. Tallene fra random funksjonen har en eller annen form for korrellasjon når man bruker de som en sekvens.
3. Tallene fra wikipedia er feil.

Har bare kodet i python i to uker så jeg anser nr.1 for å være mest sannsynlig.

Så, er det noen som ser noen feil i koden min?
Eventuelt har noen kjørt en slik simulering selv, og har noen tall jeg kunne sammenliknet med?
Sist endret av strutsefar; 19. januar 2012 kl. 12:05.
Hertugen av Dvask
Screwdriver's Avatar
Kan ikke koding, men kan det være fordi du ikke har med "0" blant tapertallene?
Kan det være fordi du genererer et tall mellom 0 og 37, men vinner/taper tallene går fra 1-38??

Kode

res = random.randint(1,38)  #Generer tilfeldig tall fra 0 til 37

Kode

#Vinnertall 21 22 23 24 25 26 27 28 29 30 21 32 33 34 35 36 37 38
#Tapertall  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 16 17 18 19 20
Sitat av Cdr. Hurricane Vis innlegg
Kan det være fordi du genererer et tall mellom 0 og 37, men vinner/taper tallene går fra 1-38??

Kode

res = random.randint(1,38)  #Generer tilfeldig tall fra 0 til 37

Kode

#Vinnertall 21 22 23 24 25 26 27 28 29 30 21 32 33 34 35 36 37 38
#Tapertall  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 16 17 18 19 20
Vis hele sitatet...
ja burde ikke 0 vert med som tapertall og tall generert burde vert 0-38?
Dette er et resultat av mye knoting med koden, kommentaren er feil.
Jeg vet(antar med stor sikkerhet) utifra frekvensen på vinnertallene at jeg genererer det riktige antallet tall. Det er 38 felter totalt på en roulette med to grønne felt. Det er typen som brukes på Wikipedia.

Jeg har da delt det opp slik allene 1-20 gir tap og 21 - 38 gir gevinst

Hadde det vert et tall for lite ville resultatet vært enda lengre fra det jeg forventer å få.
Sist endret av strutsefar; 19. januar 2012 kl. 16:22.
Hvis du deler opp koden blir det mye lettere å finne feil. Da kan du teste en og en funksjon om gangen. Eksempel:

Kode

def spin():
    res = random.randint(1, 38)
    if res > 21:
        return True
    else:
        return False


def spin_test():
    trials = 50000
    won = 0
    for i in range(1, trials):
        won += spin()
    win_chance = won/trials
    ok = abs(win_chance - (17/38)) < 0.01
    print("spin passed? ", ok, "(", win_chance, 17/38, ")")

spin_test()
Bortsett fra at det skulle være 18/38.

Tillegg: Merkelig, kan Wikipedia være feil?
Sitat av strutsefar Vis innlegg
Dette er et resultat av mye knoting med koden, kommentaren er feil.
Jeg vet(antar med stor sikkerhet) utifra frekvensen på vinnertallene at jeg genererer det riktige antallet tall. Det er 38 felter totalt på en roulette med to grønne felt. Det er typen som brukes på Wikipedia.

Jeg har da delt det opp slik allene 1-20 gir tap og 21 - 38 gir gevinst

Hadde det vert et tall for lite ville resultatet vært enda lengre fra det jeg forventer å få.
Vis hele sitatet...
Er vel bare 1 grønt felt og 37 felter totalt?
Sitat av Kråkelefse Vis innlegg
Hvis du deler opp koden blir det mye lettere å finne feil. Da kan du teste en og en funksjon om gangen. Eksempel:

Bortsett fra at det skulle være 18/38.

Tillegg: Merkelig, kan Wikipedia være feil?
Vis hele sitatet...
Takk for kodeeksemepelet, jeg har nok mye å lære både når det kommer til oversiktlighet og effektivitet.

Syns det er rart at tallene fra wikipedia skal være feil, mtp. at det da er feil for alle rundelengdene som er oppgitt. (73, 150 og 250 spins.)

Jeg kommer nok til å prøve meg med en liste tall som er generert fra random.org. Da kan jeg muligens utelukke at random modulen genererer tall som korrelerer med forrige tall.

Baconweed: Ikke på amerikanske rouletter.
Min første tanke var at randint(1,38) tok tall fra og med 1 til og med 37. Men nei..
Har sett meg totalt kodeblind, finner ingen feil. Har ikke sett noen stavefeil, som fort er et stort problem i python. Du må gjerne dobbelsjekke det (f.eks at det står deluksess istedet for delsuksess en plass). Jeg anbefaler at du skriver hele programmet fra scratch, siden du nå vet akkurat hva du skal og hvordan, og har fått litt tips her i tråden.

PS: jeg ville brukt int(input("blabla") istedet for eval(), men hva vet jeg..

PS2:
Sitat av http://www.python.org/dev/peps/pep-0008/
- Imports are always put at the top of the file, just after any module
comments and docstrings, and before module globals and constants.
Vis hele sitatet...
PS3: Du er sjukt mye flinkere en meg til å kommentere kode. Keep it up.
Sitat av snuskatten Vis innlegg

...
Du må gjerne dobbelsjekke det (f.eks at det står deluksess istedet for delsuksess en plass). Jeg anbefaler at du skriver hele programmet fra scratch, siden du nå vet akkurat hva du skal og hvordan, og har fått litt tips her i tråden.

PS: jeg ville brukt int(input("blabla") istedet for eval(), men hva vet jeg..

PS2:


PS3: Du er sjukt mye flinkere en meg til å kommentere kode. Keep it up.
Vis hele sitatet...
Hei, takk for kommentarene, jeg har dobbelsjekket for skrivefeil og kan ikke se noen skrivefeil jeg heller. Kommer til å skrive programmet på nytt litt senere i kveld for å se om jeg får samme resultater, kommer som sagt også til å prøve med helt tilfeldige tall fra random.org.

Ang eval(Input() så er det slik det gjøres i boken jeg pløyer meg igjennom. Er det noen ulemper med å bruke eval, evt fordeler med å bruke int(Input( istedenfor?

Må også inrømme at kommentarene er skrevet inn etter at jeg ikke fikk de resultatene jeg ønsket
Sitat av strutsefar Vis innlegg
...kommer som sagt også til å prøve med helt tilfeldige tall fra random.org.
Vis hele sitatet...
Det jeg vet og har erfart med random er at den fordeler uniformt(?) så lenge du har nok kall. Altså at tusen kall til randint(1,3) vil gi ganske akkurat 33.x% av henholdsvis 1, 2 og 3. Men det kan jo godt være slik som du sier at det er en viss korrelasjon mellom tallene i en rekke slik som du er ute etter.

Sitat av strutsefar Vis innlegg
Ang eval(Input() så er det slik det gjøres i boken jeg pløyer meg igjennom. Er det noen ulemper med å bruke eval, evt fordeler med å bruke int(Input( istedenfor?
Vis hele sitatet...
Har aldri brukt eval, men det du er ute etter er jo et heltall. Jeg føler at det blir overkill å bruke eval da, siden den faktisk evaluerer stringen som et python uttrykk. Dvs at om du har en variabel R = 0, så vil eval("R = 4") sette R til 4. int gir derimot heltall, som du er ute etter.

Happy coding
Hvorfor kaller du det Montecarlo-simulering?

Tenker du på Martingale, eller er det bare jeg som ikke ser Montecarlo-delen her?
Det riktig som du sier at jeg tester en Martingale strategi. Men så vidt jeg forstår kalles det en montecarlo-simulering når man kjører gjentatte tester på et problem som dette(på en datamaskin?).

http://en.wikipedia.org/wiki/Monte_Carlo_method
Sist endret av strutsefar; 20. januar 2012 kl. 16:33.
Sitat av strutsefar Vis innlegg
Det riktig som du sier at jeg tester en Martingale strategi. Men så vidt jeg forstår kalles det en montecarlo-simulering når man kjører gjentatte tester på et problem som dette(på en datamaskin?).

http://en.wikipedia.org/wiki/Monte_Carlo_method
Vis hele sitatet...
Aaah, så var det jeg selv som tenkte feil. Da jeg leste Montecarlo, tenkte jeg på Monty Hall... Beklager!
Sitat av Realist1 Vis innlegg
Aaah, så var det jeg selv som tenkte feil. Da jeg leste Montecarlo, tenkte jeg på Monty Hall... Beklager!
Vis hele sitatet...
Men dette er ingenting å beklage for! Du ga meg nettopp en glimrende idè til mitt neste prosjekt!
One of the good guys
2rs1's Avatar
Hvorfor "vinner" man etter 6 tap?
Seks tap på rad er hendelsen jeg ønsker å analysere. Derfor er det definert som en suksess når dette intreffer.

Sitat av snuskatten Vis innlegg
Det jeg vet og har erfart med random er at den fordeler uniformt(?) så lenge du har nok kall. Altså at tusen kall til randint(1,3) vil gi ganske akkurat 33.x% av henholdsvis 1, 2 og 3. Men det kan jo godt være slik som du sier at det er en viss korrelasjon mellom tallene i en rekke slik som du er ute etter.
Vis hele sitatet...

Da har jeg prøvd med tall fra random.org,fikk hentet ut litt over 1 million tall før jeg hadde brukt opp min daglige kvote. Dette ga meg ca 15 000 runder med 73.

Skrev hele programmet på nytt og benyttet disse tallene som input.

Resultatene er mer i tråd med de jeg fikk i første omgang, altså ved bruk av pythons egen random modul, enn med wikipedia sine.

Det er mulig 15 000 runder er litt i minste laget så jeg kommer til å hente mer data fra random.org etterhvert som jeg får tilgang til det.

Resultatene fra både det originale programmet og programmet som benytter tallene fra random.org: (I det originale programmet er det kjørt 100 000 runder.

Kode

73 Spins

Mitt program med tall fra random.org: 	52,09%
Mitt program fra førstepost		52,637%
Wikipedia 				50,3%


------

150 Spins

Mitt program med tall fra random.org: 	79,11%
Mitt program fra førstepost		79,379%
Wikipedia 				77,2%

------


150 Spins

Mitt program med tall fra random.org: 	92,596%
Mitt program fra førstepost		92,978%
Wikipedia 				91,1%