Currently, the range proposal supports all floating-point numbers. I briefly menโฆtioned the precision issue of floating-point numbers in https://github.com/tc39/proposal-Number.range/issues/57:
> it's rare and always have precision-related issue to iterating floats,
> so many programming languages do not support iterating floats in the core lib
We discussed this issue again at last week's JSCIG meeting, and @Jack-Works suggested me to open a separate issue since he thinks it's worth further consideration.
In short, there is always a precision issue with floating-point numbers.
For example, `range(0, 10, 3)` produces `0, 3, 6, 9`, while `range(0, 1, 0.3)` produces `0, 0.3, 0.6, 0.8999999999999999`.
There are several problems:
First, precision loss can occur with both addition and multiplication algorithm (current draft use multiplication).
Second, due to precision loss, the last value may be slightly less than `end` and included in the result. For example, `range(0, 0.9, 0.3)` produces four numbers.
Third, precision issues are sporadic, meaning that developers may write a "workable" program but easily encounter unexpected results when the parameters are slightly modified. For example, `range(100, x, 0.3)` works fine for any integer x below 166, until 166, where it becomes problematic.
Note that I think we shouldn't simply regard the precision issue of floating-point numbers as a developer education issue. Instead, we should consider under what circumstances users need to use floating-point numbers. If there are no reasonable use cases for floating-point numbers in the range, it means that using floating-point numbers almost always produces unexpected results in practice. Ultimately, MDN have to educate developers not to use floating-point numbers in the range. On the other hand, current toolchains (like TS or ESLint) don't have sufficient capabilities to warn developers against improper use of floating-point numbers during development, meaning we cannot provide protection in engineering. Therefore, it's better not to support floating-point numbers from the beginning.
So do we have enough solid use cases for the range of floating-point numbers? Based on my personal experience, it seems dubious.
For example, in the example of `range(0, 0.9, 0.3)`, I feel that most developers would expect to get the result `0, 0.3, 0.6`, meaning that what developers actually want is not floating-point numbers, but fixed-point numbers or decimals. Before decimal is introduced into JS, the most reasonable way to handle such use cases is to write `range(0, 9, 3).map(x => x / 10)`.
There may indeed be some cases where floating-point numbers are used and precision is not cared for. For example, when drawing charts, we sample several points in a certain interval on the x-axis, calculate the corresponding y values for these points, and draw them. However, in such cases, a more straightforward way is to specify the number of samples in the interval, rather than the step. Therefore, an API similar to the [`linspace` function provided by NumPy](https://numpy.org/doc/stable/reference/generated/numpy.linspace.html) would be more suitable. Of course, we can also achieve the goal through `range(0, sampleCount).map(i => start + (end - start) * i / sampleCount)`, and in this way, `range` also does not need to support floating-point numbers. (see a much real chart example: https://jsfiddle.net/f5xsopmn/ )
And, if we do not support floating-point numbers, we can also avoid the special treatment in the current proposal for special value like infinity, as well as avoid peculiar behaviors outside the safeint range (such as iteration may producing repeated numbers). Note previously #7 discussed such behavior and one suggested solution is separate float support to `range(start, end, {useFloat: true})`.
Finally, assume we only support integers in range API (throw TypeError if param is not safeint or bigint), theoretically we could upgrade it to support all float in the future, if we really want.
--
Prior arts:
Python `range()` only support integer, there are some discussions in stackoverflow, see:
- https://stackoverflow.com/questions/477486/how-do-i-use-a-decimal-step-value-for-range
- https://stackoverflow.com/questions/7267226/range-for-floats
- https://stackoverflow.com/questions/48755701/how-to-prevent-float-imprecision-from-affecting-numpy-arange