====== Zufallszahlen ====== Für Spiele und Simulationen sind Zufallszahlen äusserst nützlich. Auch für kryptographische Anwendungen werden Zufallszahlen gebraucht. Dafür sind die Zufallszahlen von Python aber **nicht geeignet**. Und sowieso: Programmieren Sie nie selbst Krypto (es sei denn, Sie machen seit 10 Jahren nichts anderes, als Kryptographie und Computerinnereien zu studieren). import random print("Floats, uniform von 0.0 bis ohne 1.0") for i in range(10): print(random.random()) # Ich bevorzuge random.randrange weil es gleich wie range funktioniert print("Ints, uniform von 0 bis und mit 3") for i in range(10): print(random.randrange(4)) # Ich rate von random.randint ab und empfehle random.randrange print("Ints, uniform von 1 bis und mit 6") for i in range(10): print(random.randint(1,6)) ''random.randrange(a,b,s)'' wählt ein zufälliges Element aus ''range(a,b,s)'' aus. Detaillierte Übersicht: https://machinelearningmastery.com/how-to-generate-random-numbers-in-python/ ===== Aufgaben ===== * Generieren Sie 10 Zufallszahlen (floats) zwischen 10.0 (inklusive) und 20.0 (exklusive). * Welchen Wert erhält man im Durchschnitt, wenn man mit zwei Würfeln auf einmal würfelt und sich jeweils den grösseren der beiden Werte notiert? * **Challenge**: Können Sie den Wert exakt berechnen? Wie sieht es mit $3$ und mehr Würfeln aus? Wie mit $n$? * Generieren Sie $n=10000$ mal einen zufälligen Punkt im Einheitsquadrat $[0,1] \times [0,1]$. Wie viele davon liegen im Einheitskreis (d.h. im Kreis mit Radius 1 um den Ursprung)? Wie viele müssten es sein? Berechnen Sie daraus eine Schätzung für $\pi$. import random print("Floats, uniform von 10.0 bis ohne 20.0") for i in range(10): print(random.random()*10+10) Simulation Maximum zweier Würfel: import random n=100000 s = 0 for i in range(n): w1 = random.randint(1,6) w2 = random.randint(1,6) if w1>w2: s+=w1 else: s+=w2 print("Durchschnitt (mit n=%d Versuchen): %f" % (n,s/n)) Oder noch eine kompaktere Variante mit Arrays: import random n=100000 numWurfel=2 s = 0 for i in range(n): s += max([random.randint(1,6) for j in range(numWurfel)]) print("Durchschnitt (mit n=%d Versuchen und %d Würfeln): %f" % (n,numWurfel,s/n)) Und exakt (durch Aufzählen aller Möglichkeiten) n = 0 s = 0 for w1 in range(1,7): for w2 in range(1,7): s+=max(w1,w2) n+=1 print("Durchschnitt exakt %d/%d ~ %f" % (s,n,s/n)) Allgemein exakt. Um die Mathematik zu verstehen, denken Sie sich für n=2 Würfel ein 6x6 Raster und markieren Sie jene Felder, die zu einem gegebenen Maximum $m$ führen. Deren Anzahl kann als Differenz zweier Quadrate (bzw. Hyperwürfel für $n>2$) berechnet werden. numWurf = 2 n = 6**numWurf s = 0 for w in range(1,7): s+=w*(w**numWurf-(w-1)**numWurf) print("Durchschnitt exakt %d/%d ~ %f" % (s,n,s/n)) import random n = 1000000 s = 0 for i in range(n): r = random.random()**2+random.random()**2 if (r<=1): s+=1 print("Durchschnitt %f, Schätzung für pi ~ %f" % (s/n, s/n*4))