6

I am trying to make this thing where it generates 7 random numbers. I am using

function getRandomInt(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
}

function generateNum(max, thecount) {
    var r = [];
    var currsum = 0;
    for (var i = 0; i < thecount - 1; i++) {
        r[i] = getRandomInt(15, max - (thecount - i - 1) - currsum);
        currsum += r[i];
    }
    r[thecount - 1] = max - currsum;


    return r;

}

This will sometimes return numbers that are NaN or are greater than 40 (which needs to be the max)

or less than 15 (which needs to be the min) and even less than 0.

It generates numbers that add up to another random number which is somewhere between 110 or 150.

How can I make it add up to the total random number and still be in a certain range?

user3756718
  • 103
  • 1
  • 9
  • So you want to generate 7 random numbers that add up to 40? – Downgoat May 09 '15 at 16:55
  • Yes and no. I want to generate 7 random numbers that add up to another random number between 110 and 150. It also each number needs to be in between 15 and 100. – user3756718 May 09 '15 at 16:57
  • What does it do instead? Also, I don't see all of these requirements in the code. Is there more code? Please see http://stackoverflow.com/help/mcve – Paul May 09 '15 at 18:36
  • Does this answer your question? [Getting N random numbers whose sum is M](https://stackoverflow.com/questions/2640053/getting-n-random-numbers-whose-sum-is-m) – Mahozad Aug 24 '21 at 16:41

1 Answers1

3

We must ensure that it is possible to have numbers such that we can reach the minimum total, and numbers such that we can not exceed the maximum total.

For each number, recalculate the its minimum and maximum value such that the intended sum is still reachable.

function getRandomInt(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
}

function randomInts(n, min, max, minSum, maxSum) {
    if (min * n > maxSum || max * n < minSum) {
       throw 'Impossible';
    }

    var ints = [];
    while (n--) {
        // calculate a lower bound for this number
        // n * max is the max of the next n numbers
        var thisMin = Math.max(min, minSum - n * max);
        // calculate an upper bound for this number
        // n * min is the min of the next n numbers
        var thisMax = Math.min(max, maxSum - n * min);

        var int = getRandomInt(thisMin, thisMax);
        minSum -= int;
        maxSum -= int;
        ints.push(int);
    }
    return ints; 
}

For completeness, I should point out there are several possible ways you could chose the probability distribution. This method at least ensures that every possible combination of integers has non-zero probability.

Paul Draper
  • 78,542
  • 46
  • 206
  • 285
  • 2
    An explanation to accompany your code would be nice. – Seiyria May 09 '15 at 17:04
  • @Seiyria, but shouldn't we write "self-documenting code"? ;) Explanation added. – Paul Draper May 09 '15 at 17:07
  • 1
    That's pretty simple. [Here's what I was going to post](http://pastebin.com/aSRjipKC) :P – Downgoat May 09 '15 at 17:11
  • 1
    Your code output doesn't match requirements of question, ie: calls of `randomNumbers(7,15,100,110,150)` produced 7 numbers that had number(s) over the 15-100 range, and when added up were over the 110-150 range: sample output `[48, 17, 56, 40, 69, 46, 108]` – Patrick Evans May 09 '15 at 17:21
  • 1
    Self-documenting code is good, but I shouldn't have to run a diff to see where two visually-similar blocks of code differ. – Seiyria May 09 '15 at 17:31
  • Thank you all so much. This was unbelievably helpful. – user3756718 May 09 '15 at 17:33
  • @PaulDraper this new version it always returns undefined. – user3756718 May 12 '15 at 10:17
  • @PaulDraper I was also wondering how you can make it add to certain number because in both designs they don't add up to a certain number if the max = min. – user3756718 May 12 '15 at 10:20