In today’s Programming Praxis problem we have to implement two ways of calculating pi. Let’s get started, shall we?
import Control.Monad import System.Random
The first algorithm is the Monte Carlo method. Sadly, the need for monads and the int-float conversion make this code less concise than it could be.
monteCarloPi :: Int -> IO () monteCarloPi n = do hits <- fmap sum $ liftM2 (zipWith checkHit) rs rs print $ fromIntegral hits / fromIntegral n where rs = replicateM n $ randomRIO (0,1 :: Double) checkHit x y = if x*x + y*y < 1 then 4 else 0
Next up is Archimedes’ algorithm.
boundPi :: Int -> (Double, Double) boundPi n = iterate f (3/2 * sqrt 3, 3 * sqrt 3) !! (n - 1) where f (b, a) = let x = 2 / (1 / a + 1 / b) in (sqrt $ b * x, x)
A quick test to see if everything is working correctly:
main :: IO () main = do monteCarloPi 10000 print $ boundPi 6
Everything seems to be in order. Of course, we could just say
main = print pi