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

From: Konrad Hinsen (konrad.hinsen at fastmail.net)
Date: Fri Feb 27 03:00:47 EST 2015

On 26/02/2015 15:13, Neil Toronto wrote:

> The second alternative is a little harder to get right because of
> fencepost errors [1]. Fortunately, Racket has a library function for it.
> Unfortunately, it's buried in `plot/utils`. Here it is in action:
>
>  > (require (only-in plot/utils linear-seq))
>
>  > (linear-seq 0.0 1.0 4)
> '(0.0 0.3333333333333333 0.6666666666666666 1.0)

That's the best solution in my opinion.

> I should really move this function into `math/base`.

Yes!

> If you must use a flonum step size, do something like this:
>
>    (define (flonum-range start end step)
>      (define n (exact-ceiling (/ (- end start) step)))
>      (for/list ([i  (in-range 0 n)])
>        (+ start (* i step))))
>
> To get points with 0.5 ulp error each, which is the best you can do, add
> (require math/flonum) to your program and change the loop body to (flfma
> step (fl i) start).
>
> Arguably, `in-range` should do something like the above when given
> floating-point step lengths. I don't know how feasible that is, though.

It would obviously break backward compatibility. And it would complicate 
the rather simple mental model one can have of in-range.

More fundamentally, I am not sure it would be much of an advantage. 
Think of the two kinds of users:

1) Those who are not aware of the problem. They will still fall into the 
trap, only a bit later, and the cause of the problem will be even more 
hidden. It's a bit like languages that do decimal rounding of float output.

2) Those who are aware of the problem. They would use linear-seq, but 
might prefer the modified in-range in specific situations for compactness.

I suspect group 1) is the bigger one, so the most important measure is 
to promote linear-seq instead of in-range for floats.

Konrad.


Posted on the users mailing list.