Tie koodariksi

Programmeringens grunder

Språk:

Kapitel 15: Slumpmässighet

När vi kombinerar en dators effektivitet med slumpmässighet kan vi undersöka slumpmässiga fenomen med hjälp av programmering. Meningen är att simulera ett fenomen många gånger på en dator och samla in data om hur det beter sig.

Slumptal

I Python finns verktygen som anknyter till slumpmässighet i biblioteket random, som måste inkluderas i början av programmet. Ofta är den nödvändiga funktionen randint(a,b) som ger ett slumpmässigt heltal i intervallet a...b. Till exempel kastar följande program tärning genom att lotta ut ett slumptal i intervallet 1...6 för variabel x.

from random import *

x = randint(1,6)
print(x)

Alltid när vi kör detta program skriver det ut något tal i intervallet 1...6. Om vi till exempel kör programmet tre gånger kan det skriva ut följande tal:

2

6

5

Nu har vi alltså ett sätt att producera så mycket slumpmässiga tal som vi behöver.

Genomförande av simuleringen

Nu ska vi granska ett prov där vi kastar tärning tills vi har fått varje poängtal åtminstone en gång. Vi vill uppskatta hur många gånger i medeltal man måste kasta en tärning innan alla poängtal har förekommit. Med andra ord vill vi räkna ut väntevärdet för det nödvändiga antalet kast.

En möjlig kastserie är [5,4,3,3,6,1,1,5,6,5,2], som består av 11 kast. I detta fall fick vi alla andra poängtal rätt fort, men vi måste kasta många gånger till för att få poängtalet 2 som saknades.

Ifall vi har riktigt god tur och varje kast ger olika poängtal är det klart att den minsta möjliga kastserien är 6. Å andra sidan kan man föreställa sig att varje poängtal helt säkert måste ha förekommit efter 100 kast. Men vad kan medeltalet för de kast som behövs vara?

Genom att genomföra en simulering på datorn kan vi undersöka hur många kast som behövs. Följande kod kastar tärning tills alla poängtal har förekommit:

from random import *

kast = []
saknas = 6

while saknas > 0:
    x = randint(1,6)
    if x not in kast:
        saknas -= 1
    kast.append(x)
print(kast)
print(len(kast))

Koden skapar listan kast, där kastserien lagras samt variabeln saknas, som innehåller antalet poängtal som saknas (först 6). Koden kastar tärning i slingan och minskar de värden som saknas med ett om den får ett poängtal som den inte ännu har fått. Sedan lägger programmet till ett poängtal till kastserien. Slingan fortsätter så länge som minst ett poängtal saknas. Till slut skriver koden ut kastserien och dess längd.

Nu kan vi testa med att köra koden ett antal gånger. Då kan vi till exempel få följande resultat:

[4, 3, 5, 1, 4, 3, 5, 3, 5, 5, 3, 3, 1, 2, 6]
15

[5, 3, 6, 5, 4, 5, 2, 1]
8

[5, 3, 5, 4, 6, 3, 3, 5, 5, 3, 5, 5, 6, 2, 2, 4, 6, 1]
18

Här var vi tvungna att kasta tärningen 15 gånger första gången, 8 gånger andra gången och 18 gånger tredje gången.

Upprepa simuleringen

För att vi ska kunna skapa oss en bra bild av fenomenet räcker dock enskilda simuleringar inte till, utan vi måste repetera simuleringen ett stort antal gånger och räkna ut medeltalet av resultaten. Detta kan vi behändigt göra genom att göra en slinga som repeterar simuleringen n gånger. Följande program kör detta:

from random import *

n = 100
s = 0

for i in range(n):
    kast = []
    saknas = 6
    while saknas > 0:
        x = randint(1,6)
        if x not in kast:
            saknas -= 1
        kast.append(x)
    s += len(kast)

print(s/n)

I början av programmet definierar n hur många gånger simuleringen upprepas (här 100 gånger) och s är summan av alla resultat. Sedan upprepar programmet simuleringen n gånger och räknas till slut det genomsnittliga antalet kast genom att dividera summan av resultaten med n.

Nu kan vi bara köra programmet och få en uppskattning av hur många kast som behövs. Vi kan påverka uppskattningens exakthet genom att ändra värdet för n. Följande tabell visar resultaten för några olika värden:

upprepningar (n)uppskattning av antalet kast (s/n)
1012.6
10014.61
100014.41
1000014.6266
10000014.70495

Det verkar alltså som om vi måste kasta i medeltal 14–15 gånger innan vi har fått varje poängtal minst en gång.

Ju större n är, desto mer övertygade kan vi vara om att värdet ligger nära sanningen. Å andra sidan, ju större n är, desto längre tar det att köra programmet. Vi måste alltså hitta en lämplig balans i förhållande till hur exakt vi vill att resultatet ska vara och hur länge vi är beredda att vänta.

Hur långt ligger uppskattningen från verkligheten? Med hjälp av sannolikhetskalkyl är det möjligt att räkna ut att det exakta väntevärdet är 14.7, vilket är nära det resultat som simuleringen ger. Så är det i allmänhet: vi får en bra bild av det slumpmässiga fenomenet genom att upprepa det tillräckligt många gånger på dator.


Uppgift 1 Olöst

Följande statistik visar resultatet av en simulation där ett mynt har kastats 100 gånger:

47 53

Det betyder att det kom 47 gånger krona och 53 gånger klave.

Genomför en motsvarande simulation där ett mynt kastas 1000 gånger.

Skriv ditt program här:


Uppgift 2 Olöst

Följande statistik visar resultatet av en simulation där en tärning har kastats 100 gånger:

14 12 18 23 14 19

Det betyder att det kom 14 gånger poängtal 1, 12 gånger poängtal 2, etc.

Genomför en motsvarande simulation där en tärning kastas 1000 gånger.

Skriv ditt program här:


Uppgift 3 Olöst

Din uppgift är att uppskatta vad är i medeltal summan av poängtal när du kastar tärning tre gånger. Om du till exempel kastar [4,3,6], är summan 13.

Skriv ett program som skriver ut uppskattningen.

Skriv ditt program här:


Uppgift 4 Olöst

Din uppgift är att uppskatta hur stor är i medeltal det större av två slumpmässiga heltal mellan 1...100. Om talen till exempel är [43,78], är det större tal 78.

Skriv ett program som skriver ut uppskattningen.

Skriv ditt program här:


Uppgift 5 Olöst

Din uppgift är att uppskatta hur stor är i medeltal skillnaden av två slumpmässiga heltal mellan 1...100. Om talen till exempel är [43,78], är skillnaden 35.

Skriv ett program som skriver ut uppskattningen.

Skriv ditt program här:


Uppgift 6 Olöst

Din uppgift är att uppskatta hur många gånger behöver du i medeltal kasta tärning tills du har fått tre samma poängtal i rad.

Skriv ett program som skriver ut uppskattningen.

Skriv ditt program här: