Generate n random numbers whose sum is m and all numbers should be greater than zero
The following is basically what you were trying to achieve. Here, it's written in Perl, since I don't know Java well, but it should be easy to translate.
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.
The problem with your approach is that you'll end up with a lot of small numbers. Five sample runs with the numbers in ascending order:
- 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
A better approach might be to take N random numbers, then scale them so their sum reaches M. Implementation:
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);
Five sample runs:
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