Glynn Clements glynn at gclements.plus.com
Wed Oct 27 09:33:39 EDT 2004

```Stijn De Saeger wrote:

> Thanks for the explanation, at first it seemed like enumFromThenTo
> would indeed give me the functionality I am looking for. But then all
> of GHCi started acting weird while playing around... this is a
> copy-paste transcript from the terminal.
>
> *S3> 0.5 `elem` [0.0,0.1..1.0]
> True
> *S3> 0.8 `elem` [0.6,0.7..1.0]
> False
> *S3> 0.8 `elem` [0.6,0.7..1.0]
> False
> *S3> [0.6,0.7..0.9]
> [0.6,0.7,0.7999999999999999,0.8999999999999999]
> *S3>
>
> ????????

Floating point has limited precision, and uses binary rather than
decimal, so you can't exactly represent multiples of 1/10 as
floating-point values. Internally, the elements of the list would
actually be out by a relative error of ~2e-16 for double-precision,
~1e-7 for single precision, but the code which converts to decimal
representation for printing rounds it.

Prelude> [6/10 :: Rational,7/10..9/10]
[3 % 5,7 % 10,4 % 5,9 % 10]
Prelude> 4/5 `elem` [6/10 :: Rational,7/10..9/10]
True

> > However, you can't specify infinitesimally small steps, nor increment
> > according to the resolution of the floating point type (at least, not
> > using the enumeration syntax; you *could* do it manually using integer
> > enumerations and encodeFloat, but that wouldn't be particularly
> > practical).
>
> Is this what you were referring to? i wouldn't say 0.1 is an
> infinitesimal small step.

No; you could realistically use much smaller steps than that. My point
was that you can't realistically use sufficiently small steps that
values won't "fall through the cracks":

Prelude> 0.61 `elem` [0.6,0.7..0.9]
False

Whilst you could, without too much effort, enumerate a range of
floating-point values such that all intermediate values were included,
the resulting list would be massive. Single precision floating-point
uses a 24-bit mantissa, so an exhaustive iteration of the range
[0.5..1.0] would have 2^24+1 elements.

--
Glynn Clements <glynn at gclements.plus.com>
```