У меня такой код:
function myArr(N){
let arr = [];
function randomNumber(min,max) {
if (min > max) {
let vMin = min;
min = parseInt(max,10);
max = parseInt(vMin,10);
}
return Math.floor(Math.random()*(max-min+1)+min);
}
for(let i = 0; i < N; i++) {
arr.push(randomNumber(100,-100));
}
return arr;
}
Эта функция генерирует массив с N числами. Но я хочу, чтобы сумма этих сгенерированных чисел была равна 0. Как это сделать? Я думал об условном «если», но точно не знаю, как его использовать в этом случае ... Может, некоторые из вас знают, как это сделать? Спасибо за любые советы!
сгенерируйте n-1 случайных чисел, затем сложите их, пусть последним будет 0-sum, sum+0-sum всегда 0, проблема решена.
вы можете использовать алогритм, который использует подход, проверяя минимальное и максимальное количество случайного значения плюс смещение, как в этом отвечать



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


При генерации чисел вы должны следить за тем, чтобы числа оставались близкими к нулю, затем вы генерируете N - 1 чисел и вычисляете последнее:
const arr = [];
let sum = 0;
for(let i = 0; i < N - 2; i++) {
let number;
if (sum >= 100) {
number = randomNumber(100 - sum, -100);
} else if (sum <= -100) {
number = randomNumber(100, -100 - sum);
} else {
number = randomNumber(100, -100);
}
sum += number;
arr.push(number);
}
arr.push(Math.floor(-sum / 2), Math ceil(-sum / 2));
(Не работает для N <4)
@iwona рада помочь :)
К вашему сведению - во время тестирования я заметил, что ваше решение, похоже, выдает числа от -100 до 100, которые, хотя и не являются однородными, с течением времени распределяются более равномерно, чем мое. Я не знаю, как это происходит.
@ גלעד ברקן может быть потому, что вы использовали функцию OPs randomNumber, которая исключает нижнюю границу. Поэтому случайные числа сужаются до одного на каждой итерации.
Спасибо, но после просмотра я не уверен, что это причина. Функция OPs randomNumber, похоже, отлично работает с параметрами, которые ей передает мое решение (они всегда заказываются (low, high)).
Есть много способов сгенерировать массив случайно сгенерированных значений, которые в сумме дают ноль, но все они по-разному влияют на распределение значений.
Например, один из простых подходов - сначала сгенерировать значения и вычислить их среднее значение, а затем вычесть это среднее из каждого значения. Следствием этого является то, что значения могут выйти за пределы диапазона, который вы изначально хотели; например, если вы случайным образом сгенерируете [100, 100, 100, -100], то среднее значение будет 50, так что вы получите [50, 50, 50, -150]. Вы можете компенсировать это, начав с более узкого диапазона, чем вам действительно нужно; но тогда это означает, что значения в этом более узком диапазоне или рядом с ним будут появляться с гораздо большей вероятностью, чем значения, близкие к концу вашего полного диапазона.
Другой простой подход - генерировать только значения n / 2, и для каждого генерируемого вами значения включать как это значение, так и его обратное арифметическое значение (например, если вы генерируете 37, тогда ваш результат будет включать как 37, так и -37). Затем вы можете случайным образом перемешать результат; так, например, если вы случайным образом сгенерируете [17, -84, 12], тогда ваш окончательный массив может быть [-12, 17, -84, -17, 84, 12].
. . . все это означает, что вам необходимо выяснить свои точные требования. Случайность - это сложно!
Случайность - это просто. Единообразие сложно. :-) Ни один из ответов не дает единообразия.
@rici: «Сложный» - это не противоположность «легкому», а «простому». Randomess сложен, потому что гораздо проще сделать что-то «случайное», чем убедиться, что это действительно то, что вы хотели. Люди обычно хотят чего-то более конкретного, чем просто "случайное", но не знают, как это сделать точным. (Вы упоминаете единообразие [в какой-то области]; еще одним распространенным неявным желанием является неповторение.)
Думаю, мы согласны с тем, что случайность - это просто. Как вы указали, сложно (что противоположно легкому) сформулировать точные требования. После того, как сформулированы, будет легче найти подходящее решение, но решение вполне может быть сложным. Алгоритмы, которые обеспечивают единообразную выборку с заменой или без замены по всей области решения, как правило, попадают в эту категорию. Случайный: :-)
Вот еще способ. Начните с нуля и разделите случайный элемент массива N-1 раз:
function myArr(N){
let arr = [0];
function randomNumber(min,max) {
if (min > max) {
let vMin = min;
min = parseInt(max,10);
max = parseInt(vMin,10);
}
return Math.floor(Math.random()*(max-min+1)+min);
}
function split(n){
let low = Math.max(-100, n - 100);
let high = Math.min(100, n + 100);
let r = randomNumber(low, high);
return [r, n - r]
}
for(let i = 0; i < N-1; i++) {
let idx = ~~(Math.random() * arr.length);
let newNums = split(arr[idx]);
arr[idx] = newNums[0];
arr.push(newNums[1]);
}
return arr;
}
console.info(myArr(5));Спасибо за это решение :)
@IwonaHajczewska на самом деле, тестирование показывает, что ответ Йонаса Вильмса, похоже, дает числа от -100 до 100, которые, хотя и не являются однородными, с течением времени распределяются более равномерно, чем это решение. Я хотел бы больше узнать о том, как это происходит, но, в зависимости от ваших потребностей, вы, возможно, были более правы, выбрав этот ответ.
@ גלעדברקן: "Не единообразно" в каком домене? Требование OP о том, что сумма чисел равна нулю, означает, что следует ожидать некоторого смещения в сторону нуля, поскольку оно исключает такие массивы, как [max, max, max, max] и [min, min, min, min], но допускает такие массивы, как [0 , 0, 0, 0]. У вашего решения также есть такая предвзятость, потому что ваш split всегда разрешает [0, n], но не всегда разрешает [max, n - max] или [min, n - min]. Не уверен, что это плохо.
@ruakh Спасибо за комментарий. Я не совсем понимаю, что вы имеете в виду, говоря о split - он всегда позволяет выбрать случайное число в максимально возможном диапазоне (например, (low, high) for -98 => [-100, 2]; (low, high) for 67 => [-33, 100].
@ רקן: Я имею в виду, что "максимальный диапазон, который он может иметь" по своей природе будет смещен в сторону нуля, поскольку этот диапазон будет включать 0 для всех значений n, будет включать 1 для 99,5% таких значений, будет включать 2 для 99 % из них и т. д., но будет включать 100 только для 50% значений.
Это мое решение, в основном вы выполняете цикл for и начинаете добавлять элементы.
Каждый раз, когда вы добавляете элемент, просто добавляйте тот же элемент * -1
У вас получится массив элементов с суммой 0.
function arrayOfSumZero(N) {
let sum = 0;
let i = N % 2 === 0 ? 0 : 1;
let output = [];
for (i; i < N; i++) {
if (output.length < N) {
sum += i;
output.push(i);
}
if (sum > 0) {
sum += i * -1;
output.push(i * -1);
}
}
return output;
}
Вычислите сумму первых чисел
n-1и вставьтеresult*-1в качестве последнего числа?