[Haskell-beginners] PI calculation - Newbie question
Felipe Lessa
felipe.lessa at gmail.com
Fri Jan 29 07:32:08 EST 2010
On Fri, Jan 29, 2010 at 12:59:30PM +0200, Gabi wrote:
> I think the problem is in "rs <- sequence (replicate n isRandIn)" -
> But I don't know how to get around it (how do I get a lazy sequence of
> rs? Is it the problem anyway?)
First of all, we don't like to be inside IO just for getting
random numbers. It is better to write, for example,
type Point = (Double, Double)
randPoint :: StdGen -> (Point, StdGen)
randPoint gen = let (x, gen') = randomR (0,1) gen
(y, gen'') = randomR (0,1) gen'
in ((x,y),gen'')
and then thread the generator yourself
randPoints :: StdGen -> [Point]
randPoints gen = let (p,gen') = randPoint gen
in p : randPoints gen' -- lazy!
To use those functions, something like
import Control.Applicative ((<$>))
inCirc :: Point -> Bool
inCirc = ...
calcPi :: Int -> [Point] -> Double
calcPi n pts = let s = length $ filter inCirc $ take n pts
in 4 * fromIntegral s / fromIntegral n
main = do pi <- calcPi 10000 . randPoints <$> newStdGen
print pi
I haven't tested performance, but it shouldn't be worse :), and
it's cleaner and more idiomatic. To be even clearer you could
use MonadRandom[1] which encapsulates the passing of StdGen between
computations.
[1] http://hackage.haskell.org/package/MonadRandom
However System.Random (used by MonadRandom as well) is known to
be very very very very slow. If you want more performance then
you should use one of the other PRNG libraries on Hackage:
http://hackage.haskell.org/package/mwc-random
http://hackage.haskell.org/package/mersenne-random
http://hackage.haskell.org/package/gsl-random
The reason why System.Random is slow is because it must support
'split', which none of the packages above support.
HTH,
--
Felipe.
More information about the Beginners
mailing list