[racket] Inconsistency of `in-range` and numerical issues

From: Konrad Hinsen (konrad.hinsen at fastmail.net)
Date: Tue Feb 24 13:11:30 EST 2015

On 24/02/2015 16:41, Laurent wrote:

> I've discovered a rather troubling behaviour when using `in-range` with
> floating point numbers, which I think is worth knowing in case you
> hadn't consider the issue before:
>
> On my machine, I get the following:
>
> (length (for/list ([i (in-range .1 .7 .1)]) i)) ; 6
> (length (for/list ([i (in-range .1 .8 .1)]) i)) ; 8 (!)
>
> But:
> (length (for/list ([i (in-range 1/10 7/10 1/10)]) i)) ; 6
> (length (for/list ([i (in-range 1/10 8/10 1/10)]) i)) ; 7
>
>
> Would it be a good idea to safe-guard these kinds of cases directly in
> `in-range`?

The problem is an old one that already troubled programmers in the age 
of Fortran. I suspect there is no reasonable safe-guard, with 
"reasonable" meaning that it does what people expect in all situations.

The only way to stay out of trouble is to avoid loops defined by an 
accumulating floating-point value. This means either don't use floats 
(write the loop over integers or rationals and convert to floats when 
using the loop index), or don't use accumulation (define your range by 
two points and the number of subdivisions, rather than the width of 
subintervals).

Konrad.


Posted on the users mailing list.