Monte-Carlo-Berechnung von Pi in Scala

8

Angenommen, ich möchte Pi mit Monte-Carlo-Simulation als Übung berechnen.

Ich schreibe eine Funktion, die zufällig einen Punkt in einem Quadrat (0, 1), (1, 0) auswählt und prüft, ob der Punkt innerhalb des Kreises liegt.

%Vor%

Dann schreibe ich eine Funktion, die als Argumente die Testfunktion und die Anzahl der Versuche verwendet und den Bruchteil der Versuche zurückgibt, in denen der Test als wahr erkannt wurde.

%Vor%

... und ich kann Pi

berechnen %Vor%

Nun frage ich mich, ob monteCarlo function verbessert werden kann. Wie würdest du monteCarlo effizient und lesbar schreiben?

Zum Beispiel, da die Anzahl der Versuche groß ist, lohnt es sich, ein view oder iterator anstelle von Range(1, trials) und reduce anstelle von map und sum zu verwenden?

    
Michael 03.09.2014, 14:48
quelle

6 Antworten

2

Stream-basierte Version, für eine andere Alternative. Ich denke, das ist ziemlich klar.

%Vor%

(Die sum ist nicht auf Streams spezialisiert, aber die Implementierung (in TraversableOnce) ruft nur foldLeft auf, das spezialisiert ist und "GC erlaubt, auf dem Weg zu sammeln." Also wird die .sum den Stream nicht erzwingen ausgewertet werden und so nicht alle Versuche auf einmal behalten)

    
The Archetypal Paul 03.09.2014, 15:36
quelle
6

Es ist bemerkenswert, dass Random.nextDouble eine Nebenwirkung hat - wenn Sie es aufrufen, ändert sich der Zustand des Zufallszahlengenerators. Das mag Sie nicht stören, aber da es hier bereits fünf Antworten gibt, denke ich, dass es nichts schaden wird, ein rein funktionelles hinzuzufügen.

Zuerst benötigen Sie eine Monad Implementierung für die Zufallsgenerierung. Glücklicherweise bietet NICTA ein wirklich nettes , das in Scalaz integriert ist. Du kannst es so benutzen:

%Vor%

Und dann:

%Vor%

Es wurde noch nichts berechnet - wir haben gerade eine Berechnung erstellt, die unseren Wert bei der Ausführung zufällig generiert. Lassen Sie es einfach vor Ort in der IO monad aus Gründen der Bequemlichkeit ausführen:

%Vor%

Dies wird nicht die performanteste Lösung sein, aber es ist gut genug, dass es für viele Anwendungen kein Problem darstellt, und die referentielle Transparenz kann sich lohnen.

    
Travis Brown 04.09.2014 00:44
quelle
2

Ich sehe kein Problem mit der folgenden rekursiven Version:

%Vor%     
Will Fitzgerald 03.09.2014 15:22
quelle
2

Und auch eine foldLeft-Version:

%Vor%

Dies ist effizienter als die map Version in der Frage.

    
Will Fitzgerald 03.09.2014 15:46
quelle
1

Die Tail-Rekursion könnte eine Idee sein:

%Vor%     
Ashalynd 03.09.2014 14:57
quelle
1

Verwenden von aggregate für eine parallele Sammlung, wie diese,

%Vor%

wobei die Teilergebnisse parallel zu anderen Testberechnungen summiert werden.

    
elm 03.09.2014 16:29
quelle

Tags und Links