oneguy,
Я понял, у меня вся фигня в том, что:
points[0, 0]
приводит к
result[0, 0, 1]
(вероятность 25%)
points[1, 1]
приводит к
result[1, 0, 0]
(вероятность 25%)
points[0, 1]
и
points[1, 0]
одинаково приводят к
result[0, 1, 0]
(вероятность 50%)
function SplitNum (sum, summands, min) {
if (summands < 1 || summands * min > sum) { return []; }
var i, range = sum - summands * min, points = [], result = [];
for (i=0; i<summands-1; i++) { points[i] = Math.floor(Math.random() * (range + 1)); }
points.push(0, range);
points.sort(function (a, b) { return a - b; });
for (i=0; i<summands; i++) { result[i] = points[i+1] - points[i] + min; }
return result;
}
function testDistribution (range, iterations) {
var i, counter = [];
for (i=0; i<range; i++) { counter[i] = 0; }
for (i=0; i<iterations; i++) { counter[SplitNum(1, range, 0).indexOf(1)]++; }
return counter;
}
alert(testDistribution(10, 10000));
В идеале распределение должно быть линейным, то есть все числа должны быть близки к 1000, но здесь явно имеем отклонение, близкое к среднеквадратическому.
Тогда просто перемешаем результат перед возвратом:
function SplitNum (sum, summands, min) {
if (summands < 1 || summands * min > sum) { return []; }
var i, range = sum - summands * min, points = [], result = [];
for (i=0; i<summands-1; i++) { points[i] = Math.floor(Math.random() * (range + 1)); }
points.push(0, range);
points.sort(function (a, b) { return a - b; });
for (i=0; i<summands; i++) { result[i] = points[i+1] - points[i] + min; }
for (i=0; i<summands-1; i++) { // перемешиваем порядок слагаемых
var j = Math.floor(Math.random() * (summands - i)) + i; // генерируем j в диапазоне [i; summands-1]
var swap = result[i]; result[i] = result[j]; result[j] = swap; // меняем местами значения по индексам i и j
}
return result;
}
function testDistribution (range, iterations) {
var i, counter = [];
for (i=0; i<range; i++) { counter[i] = 0; }
for (i=0; i<iterations; i++) { counter[SplitNum(1, range, 0).indexOf(1)]++; }
return counter;
}
alert(testDistribution(10, 10000));
Теперь всё в порядке.
Aetae,
Думаю, что
oneguy все-таки прав, потому что если при значительном количестве генераций будет наблюдаться нарушение закона больших чисел, то в зависимости от прикладной задачи это может быть не очень-то и хорошо.