3

Possible Duplicate:
Haskell ranges and floats

If I generate a list in ghci like so

let a = [0.1,1..10]

This gives me a list a with the following entries

[0.1,1.0,1.9,2.8,3.6999999999999997,4.6,5.5,6.4,7.300000000000001,8.200000000000001,9.100000000000001,10.000000000000002]

The last element of the list is 10.000000000000002, I assume this is just due to floating point use. However, comparing with the number 10 the result seems inconsistent, e.g,

last a > 10
True

last a < 10
False

Why is the list creation not comparing if the final element is less than or equal to the 10?

Community
  • 1
  • 1
petantik
  • 1,072
  • 8
  • 12

1 Answers1

6

Arithmetic sequences of floating point numbers stop when the value goes greater than the final value plus 1/2, per the reference implementation of the Prelude:

numericEnumFrom         :: (Fractional a) => a -> [a]  
numericEnumFromThen     :: (Fractional a) => a -> a -> [a]  
numericEnumFromTo       :: (Fractional a, Ord a) => a -> a -> [a]  
numericEnumFromThenTo   :: (Fractional a, Ord a) => a -> a -> a -> [a]  
numericEnumFrom         =  iterate (+1)  
numericEnumFromThen n m =  iterate (+(m-n)) n  
numericEnumFromTo n m   =  takeWhile (<= m+1/2) (numericEnumFrom n)  
numericEnumFromThenTo n n' m = takeWhile p (numericEnumFromThen n n')  
                             where  
                               p | n' >= n   = (<= m + (n'-n)/2)  
                                 | otherwise = (>= m + (n'-n)/2)

As for why, you'd have to ask the Committee, but it's likely that they didn't want a range to end up "incomplete", and thought having it a bit too large would be less unintuitive. With floating point, it's always going to be one or the other.

ehird
  • 40,602
  • 3
  • 180
  • 182
  • 4
    It's even more subtle than that -- ranges stop when the element is more than halfway between two steps. Try `[0.5 .. 1]` in `ghci` to see what I mean. – Daniel Wagner Mar 21 '12 at 17:53
  • 4
    It's pretty widely agreed that (a) this was the wrong decision, and (b) don't do that anyway - make your ranges integral, and use division to convert to floating point. That's more correct regardless of the bizarre decision. – Carl Mar 21 '12 at 18:11
  • 1
    Enumeration of floating point used to be "right" in Haskell, but it's now broken. – augustss Mar 21 '12 at 20:11