2
\$\begingroup\$

I'm taking my first steps in the Scala world, though I'm not wholly unfamiliar with functional style.

Apparently one way of calculating Pi is to sum the terms of the infinite series:

$$4 * (\frac{1}{1} - \frac{1}{3} + \frac{1}{5} - \frac{1}{7} + \frac{1}{9} \dots)$$

So I wrote this simple implementation in a Scala worksheet:

def calculatePi(tolerance: Double): Double = {
  val s1 = Iterator.continually(List(4.0, -4.0)).flatten
  val s2 = Iterator.from(0).map(_ * 2 + 1)
  s1.zip(s2).map(p => p._1 / p._2).takeWhile(math.abs(_) > tolerance).sum
}

var tolerance = 1.0
while (tolerance > .0000001) {
  val approximation = calculatePi(tolerance)
  val error = math.abs(math.Pi - approximation)
  println(s"tol:$tolerance calc:$approximation error:$error within:${error < tolerance}")
  tolerance /= 10
}

Any thoughts? If possible can anyone address these:

  • Is Iterator really the best choice here? Stream? Something else?
  • I'm particularly unhappy about the snippet map(p => p._1 / p._2); it feels like I'm missing a better way to do that.
  • Is there a better/different way to do the tolerance while loop?
  • From an algorithm standpoint, I have to decide when to stop taking values from the sequence. Is math.abs([TERM]) < tolerance a good stopping point? Or is there a better, earlier termination point?

Note: I don't really care about the println statement. It's kinda ugly but it's just there for diagnostics.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.