Good catch. Adding and subtracting over and over relying on massive
cancellation over and over is a recipe for floating point disaster!
That said, so is adding small things to a large thing over and over, you'll
accumulate the rounding error from the addition of small numbers to the
large base.
A
Way back when I started with haskell I noticed this, and switched to using
this:
-- | Enumerate an inclusive range. Uses multiplication instead of
successive
-- addition to avoid loss of precision.
--
-- Also it doesn't require an Enum instance.
range :: (Num a, Ord a) => a -> a -> a -> [a]
range
Sounds somewhat plausible. By all means give it a try.
S
-Original Message-
From: ghc-devs [mailto:ghc-devs-boun...@haskell.org] On Behalf Of Andrew Farmer
Sent: 10 August 2016 04:22
To: ghc-devs@haskell.org
Subject: enumFromThenTo for Doubles
Noticed this today:
ghci> let
Turns out the accumulated error is even worse:
Prelude> let old x y z = let eftt i j = i : eftt j (j+j-i) in let d =
y - x in maximum $ takeWhile (<= z + d) $ eftt x y
Prelude> old 0.0 0.1 86400.0
86400.005062
Prelude> let new x y z = let d = y - x in let go i = i : go (i + d) in
maximum $ tak
Noticed this today:
ghci> let xs = [0.0,0.1 .. 86400.0] in maximum xs
86400.005062
enumFromThenTo is implemented by numericEnumFromThenTo:
https://github.com/ghc/ghc/blob/a90085bd45239fffd65c01c24752a9bbcef346f1/libraries/base/GHC/Real.hs#L227
Which probably accumulates error in numericEnum