Randomly divide a value inside an array

I'm testing how to calculate the amount of loss a group of receivables has when divided in a number of installments. I have 10.000 receivables and I need to divide them randomly in a range from 1 to 12 installments, and for each value of installment I have a certain percentage of loss.

I've created an array to hold the installments and their values [loss percentage, quantity of receivables divided in that number of installments, installment group loss sum] to populate values [1,2] afterwards.

var instllmtGrp = {
     x1: [.10,0,0]
    ,x2: [.08,0,0]
    ,x3: [.06,0,0]
    ,x4: [.04,0,0]
    ,x5: [.03,0,0]
    ,x6: [.02,0,0]
    ,x7: [.01,0,0]
    ,x8: [.01,0,0]
    ,x9: [.01,0,0]
    ,x10: [.01,0,0]
    ,x11: [.01,0,0]
    ,x12: [.01,0,0]
};

When I try to create an array with 12 elements (i.e. 1/12 installments) and set a random value within the range from 1 to 10.000 to each element, I end up with a lot more than 10.000 values in total, since the math's assign a number from 1/10.000 for each array element.

var parcelas = Array.from({length: 12}, () => Math.floor(Math.random() * (10000 - 1 + 1)) + 1);

Is there a way to set a limit to the sum of the values of an array? Or to assign the random values without exceeding the 10.000?

Upvotes: 0

Views: 365

Answers (2)

Barmar
Barmar

Reputation: 782755

Create the values in a loop. After you create each value, you subtract it from the limit on the total.

var limit = 10000;
var parcelas = [];
for (var i = 0; i < 11; i++) {
  var rand = Math.floor(Math.random() * (limit - 1)) + 1;
  parcelas.push(rand);
  limit -= rand;
}
parcelas.push(limit);
console.log(JSON.stringify(parcelas));
console.log('Sum = ', parcelas.reduce((a, b) => a + b, 0));

Upvotes: 1

Kent Weigel
Kent Weigel

Reputation: 1178

You stated that you wanted random numbers adding up to 10000. In your array and in the existing answer these "random" numbers tend to be descending in value. In case that is not desired, here is a way to get random (except for the fudge factor on the last element) numbers adding up to 10000, and don't have a descending upper limit.

        var parcelas = [];
        var totalAmount = 10000;
        var sum = 0;
        var testSum = 0;
        for (var i = 0; i < 12; i++) {
            var val = Math.random();
            sum += val;
            parcelas.push(val);
        }

        for (var i = 0; i < 11; i++) {
            parcelas[i] = Math.round(parcelas[i] * totalAmount / sum);
            testSum += parcelas[i];
        }

        parcelas[11] = totalAmount - testSum;

        testSum += parcelas[11];

        console.log(parcelas.toString());
        console.log("Sum: " + testSum);

Upvotes: 0

Related Questions