
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.0000005062
Prelude> let new x y z = let d = y - x in let go i = i : go (i + d) in
maximum $ takeWhile (<= z + d) $ go x
Prelude> new 0.0 0.1 86400.0
86400.00000054126
Sorry to spam the list. :-P Floating point is hard.
On Tue, Aug 9, 2016 at 8:22 PM, Andrew Farmer
Noticed this today:
ghci> let xs = [0.0,0.1 .. 86400.0] in maximum xs 86400.0000005062
enumFromThenTo is implemented by numericEnumFromThenTo:
https://github.com/ghc/ghc/blob/a90085bd45239fffd65c01c24752a9bbcef346f1/lib...
Which probably accumulates error in numericEnumFromThen with the (m+m-n):
numericEnumFromThen n m = n `seq` m `seq` (n : numericEnumFromThen m (m+m-n))
Why not define numericEnumFromThen as:
numericEnumFromThen n m = let d = m - n in d `seq` go d n where go delta x = x `seq` (x : go delta (x + delta))
(or with BangPatterns)
numericEnumFromThen n m = go (m - n) n where go !delta !x = x : go delta (x + delta)
Seems like we'd save a lot of subtractions by using the worker function.