[Haskell-cafe] about integer and float operations
Yitzchak Gale
gale at sefer.org
Wed Feb 4 18:31:31 EST 2009
Manlio Perillo wrote:
> However there is still a *big* problem: it is inefficient.
>
> Here is a Python version of the Chudnovsky algorithm [1] for computing Pi:
> http://paste.pocoo.org/show/102800/
> On my system it takes 10 seconds.
> Here is an Haskell version:
> http://paste.pocoo.org/show/102801/
> On my system it takes 30 seconds.
Ah, OK. Thanks. Now we have a well-defined problem. :)
And that makes it clear that what you want is Python 3
division.
Well, first of all, there are a few bugs in the Haskell version
of your program - don't forget that unlike in Python, ranges
in Haskell *include* the last number.
Second, we should note that it is silly to compute
1000 terms in this sum. By the end, you are getting
terms whose order of magnitude is 10 ^ (-15000).
The Haskell version is spending a bit more time on those
(useless) later terms. The reason is that in Haskell we are
first reducing the fraction, then converting to Double. If you
really did care about that amount of accuracy, you would
leave the result as a Rational. Or as one of various
other unlimited-precision floating point types that are available
in Haskell libraries. This calculation in Haskell would take
the same amount of time as it takes now. You would need
to rewrite your Python program to do this, and I would
guess it would run a lot slower.
In our case, the Python division first does a quick estimate
of the sizes of the two integers, and just returns zero if it
sees that there will be underflow on conversion to double.
So I made the following rough change to the Haskell:
-- An exact division
(/.) :: Integer -> Integer -> Double
x /. y
| y `div` x > 5*10^323 = 0
| otherwise = fromRational $ toRational x / toRational y
Now the Haskell runs in about half the time as the Python
on my machine. Obviously, the Haskell could easily be
further optimized.
-Yitz
More information about the Haskell-Cafe
mailing list