Atlantic City Pi in Haskell

Posted by Daniel Lyons Thu, 02 Aug 2007 06:58:00 GMT

To relax after fixing the house I coded this quickie in Haskell:


atlanticCityMethod :: Float -> Float -> Float -> Float
atlanticCityMethod x m u = (u*m)/n
  where
    iterates = take (fromEnum m) $ iterate (\x -> (2 - x) / (3 - 4*x)) x
    nearZero u x = (-u)/2 < x && x < u/2
    n = fromIntegral $ length $ filter (nearZero u) iterates

I think this pretty concisely captures the specification:

Here’s the slowest, most inefficient method known for computing p: Choose an arbitrary initial value x (real) and iterate the mapping x → (2-x)/(3-4x) for a total of M times. Count the number of iterates that fall within a small interval around zero. For example, let N denote the number of iterates that fall between -u/2 and +u/2 for some small u. Then the limiting value of the ratio uM/N is p (for sufficiently large M as u goes to zero).

Observations:

  1. This algorithm is so shitty I can’t tell if it’s actually working with reasonable input (atlanticCityMethod 1029 1000000 0.00005 produced 3.125 for me, but what do I know?)
  2. Don’t like that lambda? Do the Arrow twist:

    ((2-) &&& ((4*) >>> (3-))) >>> (uncurry (/))

    This works just as well, but is twice as long and much harder to read. I guess points-free sometimes comes at a cost.

  3. The auto-derived type was much stranger than the ones I guessed it would want. Haskell inferred this type signature:

    atlanticCityMethod :: (Ord b, Fractional b, Enum b) => b -> b -> b -> b

  4. Haskell mode’s indentation is really smart, but it still pisses me off by choosing the inner-most indentation by default. I think it would be better if it chose the previous level of indentation by default. Maybe there’s an easy way to do this, but I don’t know it.
  5. Want to see a screenshot of my Haskell with pretty lambdas?

  6. Incidentally, Justin Dressel pointed out that Haskell sometimes can work with Unicode input, at least according to the Haskell` page.

Tags , ,  | no comments