To get a uniform distribution, the trick is to think of your sum as a number line, and rather than generating random numbers for the segments, generate n-1 numbers as points along the line, and subtract to get the segments. Here's the function from ojrandlib:
static int compare(const void *a, const void *b) {
return *(int*)a - *(int*)b;
}
void ojr_array_with_sum(ojr_generator *g, int *a, int count, int sum) {
int i;
for (i = 0; i < count-1; ++i) { a[i] = ojr_rand(g, sum+1); }
qsort(a, count-1, sizeof(int), compare);
a[count-1] = sum;
for (i = count-1; i > 0; --i) { a[i] -= a[i-1]; }
}
ojr_rand(g, limit)
generates a uniform random integer from 0 to limit-1. This function then fills the array a
with count
random integers that add to sum
. Shouldn't be too hard to adapt this to any other RNG.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…