[Haskell-beginners] map increases length of list

Brent Yorgey byorgey at seas.upenn.edu
Thu Jun 18 14:17:31 EDT 2009


On Thu, Jun 18, 2009 at 05:32:26PM +0200, Aai wrote:
> Check this out:
> 
> Prelude> [0,60..330]::[Double]
> [0.0,60.0,120.0,180.0,240.0,300.0,360.0]
> 
> Prelude> [0,60..329]::[Double]
> [0.0,60.0,120.0,180.0,240.0,300.0]
> 
> It looks like the decision the step to the next value in case of flt.
> point enumeration depends on >= enumWith / 2. But that should be
> answered by those who know from under the hood.

That is correct.  The reason for this is because of the inaccuracy of
floating point numbers.  For example, consider

  [0.1,0.2..10.0]

which clearly ought to contain 100 numbers, every tenth from 0.1
through 10.0 inclusive. But 0.1 cannot be represented exactly in
binary, so adding 0.1 to itself 100 times might very well give a
result like 10.0000000002.  Should this be included in the range, or
not?  After all, it's bigger than 10.0...but it would be quite
surprising if the 10.0000000002 were left out.  Hence the last number
is included even if it is up to 1/2 of a step over the end value of
the range.  But this can also be surprising at times (as the original
poster found out!).  What to do?

The answer is: don't use list enumerations for floating point
numbers!!  It is nonsensical.  Alternative options include:

  * use Rational instead of Double, which IS exact
  * use Integers for the enumeration, and then convert to Double

and so on.

-Brent


More information about the Beginners mailing list