[racket] Inconsistency of `in-range` and numerical issues
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.