Seite 1 von 1

MonteCarlo Simulation zur Approximation von pi

Verfasst: Mittwoch 10. Juni 2009, 17:45
von Sconine
Hallo zusammen,
schon wieder ich. :D

Diesmal habe ich mit einen Mitstudenten zu der Aufgabe:

Einem Kreis mit Radius 1 sei ein Quadrat dicht umschrieben: ‚Dart-Scheibe‘.
• Simulieren Sie zufällige Würfe auf die Dart-Scheibe.
• Zählen Sie die Treffer (im Kreis).
• Berechnen Sie 4 · (Treffer/Würfe).
• Vergleichen Sie mit π

folgendes Programm geschrieben:

Code: Alles auswählen

def montecarlo(N): # Funktion wird definiert

    """Auf einen Kreis in einem 1*1 großen Quadrat werden N Wuerfe simuliert.
    Sie liefert die durchschnittlichen Treffer * 4 zurueck. """ 

    from random import random # implementiert Zufallszahlen

    wuerfe, treffer = 0, 0 # bei 0 Wuerfe und Treffer wird begonnen

    while wuerfe<N: # Anweisungsblock wird solange wiederholt, bis die Bedingung
                    # eingetroffen ist (bis 

        # x und y sind die Koordinaten des geworfenen Pfeils
        # random liefert die Werte zwischen 0 und 1, zufällig

        x, y = random(), random()

        
        if (x**2+y**2)**0.5 < 1: # euklidische Abstand vom Nullpnkt wird
                                 # definiert, wenn die berechneten Abstand
                                 # kleiner 1 sind, dann wurde der Kreis getroffen

            treffer+=1

        wuerfe+=1

    return 4.*treffer/wuerfe # 4 mal werden de Treffer und Wuerfe berechnet



if __name__=='__main__':

    from math import pi # implementiert von math pi

    # Der versuch wird mit immer groesseren Anzahlen von Würfen wiederholt
    #und dann wird der Betrag des jeweiligen Abstandes zum bekannten pi berechnet

    
    for N in [1,10,100,1000,10000,100000,1000000]: # Anzahl von Wuerfen wird angegeben

        abweichung = abs(montecarlo(N)-pi) # liefert den absoluten Wert von x
                                           # (Abstand zwischen zwischen x und Null)
                                           

        print "Nach %d Wuerfen betrug die Abweichung zu pi: %f" %(N,abweichung)
Was bedeutet nochmal die Funktion _main_?
Ich wollte nun fragen, ob meine Kommentare richtig sind und ob es noch verbesserungsvorschläge gibt.
So langsam bekomme ich gefallen an Python. :)

Verfasst: Mittwoch 10. Juni 2009, 17:52
von Dill
wenn du die antworten zu deinem letzen posting gelesen hättest wüsstests du's... :o

Verfasst: Mittwoch 10. Juni 2009, 17:59
von EyDu
Noch ein paar Anmerkungen:

- Variablennamen solltest du klein schreiben, dass gilt auch für Parameter (siehe PEP8)
- die Importe sollten am Anfang des Programms stehen: das ist übersichtlicher und sie werden nicht bei jedem Funktionsaufruf ausgeführt
- die while-Schleife sollte durch eine for-Schleife ersetzt werden
- das Ziehen der Quadratwurzel ist hier überflüssig ;-)
- "# implementiert von math pi " hast du falsch verstanden: pi wird aus dem Modul math importiert
- __main__ ist übrigens keine Funktion ;-)
- Kommentare sollten über den betreffenden Zeilen stehen und nicht hinter
- und noch ein Tipp:

Code: Alles auswählen

for x in (10**i for i in range(6)):
     print x

Verfasst: Mittwoch 10. Juni 2009, 18:04
von Dill
das meiste davon hatten wir schon in seinem anderen thread.

Verfasst: Mittwoch 10. Juni 2009, 19:02
von BlackJack
Ist'n bisschen "wortreich" die `montecarlo()`-Funktion.

Code: Alles auswählen

def montecarlo(n):
    return 4.0 * sum((random()**2 + random()**2) < 1 for _ in xrange(n)) / n
Mit einem ordentlichen DocString würde ich das als lesbare Implementierung durchgehen lassen.

Verfasst: Freitag 12. Juni 2009, 10:42
von Sconine
Ich habe versucht die Tipps zu übernehmen.
Jetzt habe ich glaub ich alles kaputt gemacht.

Code: Alles auswählen

from random import random

from math import pi

def montecarlo(n):

    wuerfe, treffer = 0, 0

    #while wuerfe < n:
    for wuerfe in range (n):

        x, y = random (), random()

        if (x**2 + y**2)++0.5 < 1:

            treffer += 1

            wuerfe +=1

        return 4.*treffer/wuerfe

if __name__ == '__main__':

    #for n in [1,10,100,1000,10000,100000,1000000]:

    
    for x in (10**i for x in range(6)):
          print x
       
       #abweichung = abs(montecarlo(N)-pi) 
       # print "Nach %d Wuerfen betrug die Abweichung zu pi: %f" %(n,abweichung)
 

Ich bin schon wieder am verzweifeln... :cry:

Verfasst: Freitag 12. Juni 2009, 13:50
von Sconine
Wws habe ich denn an den Tipps falsch übernommen???

Verfasst: Freitag 12. Juni 2009, 15:46
von BlackJack
Schau Dir Dein Programm noch einmal ganz aufmerksam, Zeile für Zeile an.

Interessant ist, dass Du einen Fehler in eine Zeile eingebaut hast, die eigentlich unverändert aus Deinem ersten Beitrag stammen müsste. Da war's nämlich richtig. Wobei die Operation, wie schon angemerkt wurde, beim Einheitskreis überflüssig ist.

Verfasst: Freitag 12. Juni 2009, 15:46
von EyDu

Code: Alles auswählen

def montecarlo(n):
    treffer = 0

    for wuerfe in range(n):
        x, y = random (), random()
        if (x**2 + y**2) < 1:
            treffer += 1

    return 4.*treffer/n
- aus deinem ++ ein ** gemacht, wie gesagt kannst du das **0.5 auch weglassen
- dein return war falsch eingerückt und hat nach dem ersten Durchlauf die Schleife schon abgebrochen
- "wuerfe" brauchst du nicht extra berechnen, das entspricht n

Verfasst: Montag 15. Juni 2009, 09:53
von Sconine
Es ist zum Mäusemelken. Das Einrücken hat mir ja schon immer Probleme gemacht (wie ihr ja unschwer erkennen konntet), aber jetzt bin ich kurz vor dem Aufgeben bei dieser Aufgabe.

Code: Alles auswählen

from random import random

from math import pi

def montecarlo(n): 
    treffer = 0 

    for wuerfe in range(n): 
        x, y = random(), random() 
        if (x**2 + y**2) < 1: 
            treffer += 1 

    return 4.*treffer/n



if __name__ == '__main__':

    #for n in [1,10,100,1000,10000,100000,1000000]:

    for x in (10**i for i in range(6)):
        print x
    
    abweichung = abs(montecarlo(n)-pi)
    print "Nach %d Wuerfen betraegt die Abweichung zu pi: %f" %(n,abweichung)

Code: Alles auswählen

1
10
100
1000
10000
100000
Traceback (most recent call last):
  File "C:\Python25\Aufgabenzettel_9\MonteCarlo.ich.py", line 24, in <module>
    abweichung = abs(montecarlo(n)-pi)
NameError: name 'n' is not defined
Das kann doch nicht wahr sein? Wo habe ich denn diesmal eine Zeile falsch eingerückt???

Verfasst: Montag 15. Juni 2009, 10:08
von EyDu
Wo soll n denn auch herkommen? Du willst die Abweichung außerdem in der Schleife bestimmen, warum steht der Aufruf dann danach?

Code: Alles auswählen

if __name__ == '__main__':
    for n in (10**i for i in range(6)):
        abweichung = abs(montecarlo(n)-pi)
        print "Nach %d Wuerfen betraegt die Abweichung zu pi: %f" %(n,abweichung)

Verfasst: Montag 15. Juni 2009, 11:05
von losgehts
Hallo allerseits,

das ist mein erster Post (bin noch absoluter Frischling und komme gerade erst mit der Schlange in Berührung), habt also Nachsicht: falls ich ausversehen gegen irgendwelche Forenregeln verstoße, ist das nicht meine Absicht.

Zum Code selbst kann ich natürlich nichts beisteuern, aber ich bin der Meinung, dass die ganze Kreisfläche mit einbezogen werden sollte:

also als Prüfung statt:

Code: Alles auswählen

if x**2 + y**2 < 1:
ein KleinerGleich:

Code: Alles auswählen

if x**2 + y**2 <= 1:
Naja, klar dass das den Kuchen nicht fett macht, ist meiner Ansicht nach aber plausibler :roll: .

Oder habe ich da etwas falsch verstanden?

Grüße, Ulrich