Skip to content

Instantly share code, notes, and snippets.

@ilaborie
Created January 30, 2019 07:28
Show Gist options
  • Save ilaborie/9c4fbb7f3fce677a63a343b615612ec5 to your computer and use it in GitHub Desktop.
Save ilaborie/9c4fbb7f3fce677a63a343b615612ec5 to your computer and use it in GitHub Desktop.
Test MonteCarlo Pi en Scala
package io.github.ilaborie.loops.samples
import java.text.NumberFormat
import scala.annotation.tailrec
import scala.util.Random
object MonteCarlo {
def main(args: Array[String]): Unit = {
val format = NumberFormat.getIntegerInstance()
(2 to 7)
.map(e => Math.pow(10.0, e.toDouble).toInt)
.foreach { count =>
System.out.printf("Compute with %s ...%n", format.format(count.toLong))
val pi = monteCarloStreamParallel(count)
println(s"Result: $pi")
}
}
private val rnd = new Random()
case class Point(x: Double, y: Double) {
def inCircle(): Boolean =
x * x + y * y <= 1
}
private def compute(count: Int, inCircle: Int): Double =
inCircle.toDouble / count * 4
def monteCarloFor(count: Int): Double = {
var inCircle = 0
for (_ <- 1 to count) {
val p = Point(rnd.nextDouble(), rnd.nextDouble())
if (p.inCircle()) {
inCircle += 1
}
}
compute(count, inCircle)
}
def monteCarloRecursion(count: Int): Double = {
@tailrec
def aux(count: Int, inCircle: Int): Int =
if (count == 0) inCircle
else {
val p = Point(rnd.nextDouble(), rnd.nextDouble())
aux(count - 1, inCircle + if (p.inCircle()) 1 else 0)
}
val inCircle = aux(count, 0)
compute(count, inCircle)
}
def monteCarloStream(count: Int): Double = {
val inCircle = Stream.continually(Point(rnd.nextDouble(), rnd.nextDouble()))
.take(count)
.count(_.inCircle())
compute(count, inCircle)
}
def monteCarloStreamParallel(count: Int): Double = {
val inCircle = Stream.continually(Point(rnd.nextDouble(), rnd.nextDouble()))
.par
.take(count)
.count(_.inCircle())
compute(count, inCircle)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment