Laiso
Laiso

Reputation: 2650

Split a range of number to a specific number of intervals

I have an interval [0; max] and I want to split it into a specific number of sub-intervals. For this, i wrote a function called getIntervalls(max, nbIntervals) where max is the max element in my first interval and nbIntervals is the number of expected sub-intervals.

For example:

Here is my function:

function getIntervalls(max, nbIntervalls) {

    var size = Math.ceil(max / nbIntervalls);
    var result = [];

    if (size > 1) {
      for (let i = 0; i < nbIntervalls; i++) {
        var inf = i + i * size;
        var sup = inf + size < max ? inf + size: max;

        result .push([inf, sup]);
      }
    } else {
      result.push([0, max]);
    }

    return result;
}

console.log(JSON.stringify(getIntervalls(7, 2)));

It work properly, and shows this output:

[[0,4],[5,7]]

When I change the parameters to 7 and 3, it shows:

[[0,3],[4,7],[8,7]]

instead of

[[0,2],[3,5],[6,7]]

Would anyone can help me? Thank you in advance. An ES6 syntax will be appreciated! :)

Upvotes: 7

Views: 4259

Answers (4)

Roberto Santana
Roberto Santana

Reputation: 745

For me, this is the perfect function for that.

It allows you to get the intervals between two numbers, and the last interval always goes to the max.

function getIntervals(min, max, nbIntervals) {
    let size = Math.floor((max - min) / nbIntervals);
    let result = [];

    if (size <= 0) return [min, max];

    for (let i = 0; i < nbIntervals; i++) {
        let inf = min + (i * size);
        let sup = ((inf + size) < max) ? inf + size : max;

        if (i === (nbIntervals - 1)) {
            if (sup < max) sup = max;
        }

        result.push([inf, sup]);

        if (sup >= max) break;
    }

    return result;
}

Upvotes: 2

Mahefa
Mahefa

Reputation: 418

You need to use Math.round() for take the nearest integer of the decimal number of the size of interval. Also, you need to descrease a one the max for size calculation to take account of the effective number of interval.

Here the modification of your code :

function getIntervalls(max, nbIntervalls) {
    var size = Math.round((max-1) / nbIntervalls);
    var result = [];

    for (let i = 0; i < nbIntervalls; i++) {
        var inf = i + i * size;
        var sup = inf + size < max ? inf + size: max;

        result.push([inf, sup]);
        if(inf >= max || sup >= max)break;
    }
    return result;
}

Note that it respect the wanted number of interval, so some case of couple of number can result
[..., [n-2,n-1], [n,n]].

Hope this helps!

Upvotes: 4

zenwraight
zenwraight

Reputation: 2000

You need to change the size calculation from Math.ceil() to Math.floor(), because of ceil it takes size +1 than what you need.

I have made modification to your code, here it will work.

function getIntervalls(max, nbIntervalls) {

    var size = Math.floor(max / nbIntervalls);
    var result = [];

    if (size > 0) {
      for (let i = 0; i < nbIntervalls; i++) {
        var inf = i + i * size;
        var sup = inf + size < max ? inf + size : max;

        result .push([inf, sup]);
        if (sup >= max) {
          break;
        }
      }
    } else {
      result.push([0, max]);
    }

    return result;
}

console.log(JSON.stringify(getIntervalls(10, 5)));

Hope this helps!

Upvotes: 2

Nenad Vracar
Nenad Vracar

Reputation: 122027

You could check if i is zero for first element and if next increment is larger then max for second element. Also you can check if first element is smaller then max.

function getIntervalls(max, nInt) {
  const c = Math.floor(max / nInt);
  const r = [];
  for (var i = 0; i <= max; i += c) {
    const a = i == 0 ? i : i += 1;
    const b = i + c > max ? max : i + c;
    if (a < max) r.push([a, b])
  }
  return r;
}

console.log(JSON.stringify(getIntervalls(3, 2)));
console.log(JSON.stringify(getIntervalls(6, 2)));
console.log(JSON.stringify(getIntervalls(8, 3)));
console.log(JSON.stringify(getIntervalls(9, 3)));
console.log(JSON.stringify(getIntervalls(7, 2)));
console.log(JSON.stringify(getIntervalls(7, 3)));

Upvotes: 3

Related Questions