enumFromThenTo for Doubles

Andrew Farmer xichekolas at gmail.com
Wed Aug 10 03:27:33 UTC 2016


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 <xichekolas at gmail.com> wrote:
> 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/libraries/base/GHC/Real.hs#L227
>
> 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.


More information about the ghc-devs mailing list