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:
- This algorithm is so shitty I can’t tell if it’s actually working with reasonable input (
atlanticCityMethod 1029 1000000 0.00005produced 3.125 for me, but what do I know?) - 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.
- 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 - 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.
- Want to see a screenshot of my Haskell with pretty lambdas?
- Incidentally, Justin Dressel pointed out that Haskell sometimes can work with Unicode input, at least according to the Haskell` page.
