Generate n random numbers whose sum is m and all numbers must be greater than zero

I want to generate 9 non-zero random numbers, the sum of which is 250. I tried the following code, it gives me 9 random numbers, but some numbers are zero.

 public void n_random()
{
  Random r = new Random();
ArrayList<Integer> load = new ArrayList<Integer>();
    int temp = 0;
    int sum = 0;
    for (int i = 1; i <= 9; i++) {
        if (!(i == 9)) {
            temp = r.nextInt(250 - sum);
            System.out.println("Temp " + (i) + "    " + temp);
            load.add(temp);
            sum += temp;

        } else {
            int last = (250 - sum);
            load.add(last);
            sum += last;
        }
    }

    System.out.println("Random arraylist " + load);
    System.out.println("Sum is "+ sum);

}

Where is my mistake or where should I improve my code or any other solution?

+4
source share
7 answers

I would suggest using:

temp = r.nextInt((250 - sum) / (9 - i)) + 1;

This ensures that:

  • each number is strictly positive
  • you will not use the full "allowance 250" until reaching the 9th number.

However, the distribution of results may be biased.

Output Example:

Random Arraialist [18, 28, 22, 19, 3, 53, 37, 49, 21]

Explanation:

  • (250 - sum) - , 250,
  • / (9 - i), , , 200 ( 50), 5, , 10, 4
  • + 1 0

, , , , , . :

public static void n_random(int targetSum, int numberOfDraws) {
    Random r = new Random();
    List<Integer> load = new ArrayList<>();

    //random numbers
    int sum = 0;
    for (int i = 0; i < numberOfDraws; i++) {
        int next = r.nextInt(targetSum) + 1;
        load.add(next);
        sum += next;
    }

    //scale to the desired target sum
    double scale = 1d * targetSum / sum;
    sum = 0;
    for (int i = 0; i < numberOfDraws; i++) {
        load.set(i, (int) (load.get(i) * scale));
        sum += load.get(i);
    }

    //take rounding issues into account
    while(sum++ < targetSum) {
        int i = r.nextInt(numberOfDraws);
        load.set(i, load.get(i) + 1);
    }

    System.out.println("Random arraylist " + load);
    System.out.println("Sum is "+ (sum - 1));
}
+8

n , m,

. Perl, Java , .

use strict;
use warnings;
use feature qw( say );

use List::Util qw( shuffle );

my $m = 250;
my $n = 9;
my @nums;
while ($n--) {
   my $x = int(rand($m-$n))+1;  # Gen int in 1..($m-$n) inclusive.
   push @nums, $x;
   $m -= $x;
}

say join ', ', shuffle @nums;   # shuffle reorders if that matters.

, . :

  • 1, 1, 1, 1, 2, 3, 6, 50, 185
  • 1, 1, 1, 1, 2, 3, 4, 13, 224
  • 1, 1, 1, 1, 1, 3, 8, 11, 223
  • 1, 1, 1, 1, 2, 4, 19, 103, 118
  • 2, 2, 9, 11, 11, 19, 19, 68, 109

N , , M. :

use strict;
use warnings;
use feature qw( say );

use List::Util qw( sum );

my $m = 250;
my $n = 9;

# Generate $n numbers between 0 (incl) and 1 (excl).
my @nums;
for (1..$n) {
   push @nums, rand();
}

# We subtract $n because we'll be adding one to each number later.
my $factor = ($m-$n) / sum(@nums);

for my $i (0..$#nums) {
   $nums[$i] = int($nums[$i] * $factor) + 1;
}

# Handle loss of fractional component.
my $fudge = $m - sum(@nums);
for (1..$fudge) {
   # Adds one to a random number.
   ++$nums[rand(@nums)];
}

say join('+', @nums), '=', sum(@nums);

:

32+32+23+42+29+32+29+20+11=250
31+18+25+16+11+41+37+56+15=250
21+15+40+46+22+40+32+1+33=250
34+24+18+29+45+30+19+29+22=250
3+45+20+6+3+25+18+65+65=250
+5

:

r.nextInt(250 - sum);

... 0 () 250 - sum ( ).

. API Random.nextInt.

, 1 , 0.

, :)

, 250 - sum - 1 , IllegalArgumentException.

+3

, , . , .

" " .

0

Random.nextInt(n) 0 n-1

temp = r.nextInt(250 - sum) + 1; , .

0

, () , , .

public static void n_random(int count, int finalSum)
{
    Random r = new Random();
    int numbers[] = new int[count];
    int sum = 0;
    for (int i = 0; i < count - 1; i++)
    {
        numbers[i] = r.nextInt((finalSum - sum) / 2) + 1;
        sum += numbers[i];
    }
    numbers[count - 1] = finalSum - sum;

    StringBuilder numbersString = new StringBuilder("Random number list: ");
    for (int i = 0; i < count; i++)
        numbersString.append(numbers[i] + " ");
    System.out.println(numbersString);
}

public static void main(String[] args)
{
    n_random(9, 250);
}
0

javascript

function getRandomNos(m,n) {

    var nums=[];
    var i;

    for (i = 0;i<n;i++) {
       nums[i] = Math.random();
    }
    var factor = (m-n) / nums.reduce(add, 0);
    for (i = 0;i<nums.length;i++) {
       nums[i] = parseInt(nums[i] * factor) + 1;
    }

    var fudge = m - nums.reduce(add, 0);

    for (i=0;i<fudge;i++) {
       nums[i] = nums[i] + 1;
    }
    console.log(nums);
    console.log(nums.reduce(add, 0));

}

function add(a, b) {
    return a + b;
}
0

Source: https://habr.com/ru/post/1531588/


All Articles