JS 函数创建一个数字范围(包括开始和结束),并限制范围项

JS function that creates a range of numbers (inclusive beginning and end) with a limit on range items

您将获得起始编号和结束编号以及允许的最大输出元素数。您将如何创建一个分布尽可能均匀的输出数组,同时仍然包括输出中的第一个和最后一个点?

函数签名

function generatePoints(startingNumber, endingNumber, maxPoints) {}

函数期望输出

generatePoints(0, 8, 5) // [0, 2, 4, 6, 8]

这是我到目前为止尝试过的方法
function generatePoints(startingNumber, endingNumber, maxPoints) {
   const interval = Math.round((endingNumber - startingNumber) / maxPoints)
    let count = 0
    let counter = 0
    let points = []
   
    while(count < maxPoints - 1) {
        points.push(counter)
        counter+=interval
        count++
    }

    points.push(endingNumber)

    return points
}

从技术上讲,这为简单情况创建了正确的输出,但是在与大多数其他边缘情况相比时不够用,因为我提前停止了一次迭代,然后添加最后一点。我认为更好的方法(创建更好的分布)是从数组的中心向外构建,而不是从数组的开头构建,然后提前停止一个元素并附加 endingNumber.

不要Math.round(interval)。相反 Math.round(counter) 在最后一刻。

原因在于,如果您添加了 k 个间隔,则您所进行的操作的误差可能会达到 0.5*k。但是如果你在最后一分钟舍入,错误永远不会超过 0.5.

请注意:

  0       2       4       6        8
   +-----+ +-----+ +-----+ +-----+
      A       B       C       D

将我们的范围分成包含端点在内的 5 个点的区间,我们只有四个区间。它总是比点数少一。我们可以将我们的范围平均划分为这些更小的范围,只需不断地增加一个区间的宽度,也就是 (endingNumber - startingNumber) / (maxPoints - 1)。我们可以这样做:

const generatePoints = (startingNumber, endingNumber, maxPoints) => Array .from (
  {length: maxPoints}, 
  (_, i) => startingNumber + i * (endingNumber - startingNumber) / (maxPoints - 1)
) 

console .log (generatePoints (0, 8, 5))

我们只是构建了一个长度合适的数组,使用索引参数来计算我们正在使用的较小间隔的数量。

我们这里没有 error-checking,如果 maxPoints 只是 1,我们可能会遇到问题。但这很容易处理你喜欢的方式。


但这里有个问题。为什么参数叫 maxPoints 而不是 points?如果允许的点数是可变的,我认为我们需要进一步的要求。