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.
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?
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)
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:
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.
Ich sehe kein Problem mit der folgenden rekursiven Version:
%Vor%Und auch eine foldLeft-Version:
%Vor% Dies ist effizienter als die map
Version in der Frage.
Tags und Links scala montecarlo