Как сгенерировать N чисел в массиве, чтобы сумма этих чисел была равна 0

У меня такой код:

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 и вставьте result*-1 в качестве последнего числа?

jp-jee 21.09.2018 17:30

сгенерируйте n-1 случайных чисел, затем сложите их, пусть последним будет 0-sum, sum+0-sum всегда 0, проблема решена.

Vaibhav Vishal 21.09.2018 17:32

вы можете использовать алогритм, который использует подход, проверяя минимальное и максимальное количество случайного значения плюс смещение, как в этом отвечать

Nina Scholz 21.09.2018 17:35
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
2
3
2 810
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

При генерации чисел вы должны следить за тем, чтобы числа оставались близкими к нулю, затем вы генерируете 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 рада помочь :)

Jonas Wilms 21.09.2018 17:46

К вашему сведению - во время тестирования я заметил, что ваше решение, похоже, выдает числа от -100 до 100, которые, хотя и не являются однородными, с течением времени распределяются более равномерно, чем мое. Я не знаю, как это происходит.

גלעד ברקן 22.09.2018 15:02

@ גלעד ברקן может быть потому, что вы использовали функцию OPs randomNumber, которая исключает нижнюю границу. Поэтому случайные числа сужаются до одного на каждой итерации.

Jonas Wilms 22.09.2018 16:01

Спасибо, но после просмотра я не уверен, что это причина. Функция OPs randomNumber, похоже, отлично работает с параметрами, которые ей передает мое решение (они всегда заказываются (low, high)).

גלעד ברקן 22.09.2018 16:48

Есть много способов сгенерировать массив случайно сгенерированных значений, которые в сумме дают ноль, но все они по-разному влияют на распределение значений.

Например, один из простых подходов - сначала сгенерировать значения и вычислить их среднее значение, а затем вычесть это среднее из каждого значения. Следствием этого является то, что значения могут выйти за пределы диапазона, который вы изначально хотели; например, если вы случайным образом сгенерируете [100, 100, 100, -100], то среднее значение будет 50, так что вы получите [50, 50, 50, -150]. Вы можете компенсировать это, начав с более узкого диапазона, чем вам действительно нужно; но тогда это означает, что значения в этом более узком диапазоне или рядом с ним будут появляться с гораздо большей вероятностью, чем значения, близкие к концу вашего полного диапазона.

Другой простой подход - генерировать только значения n / 2, и для каждого генерируемого вами значения включать как это значение, так и его обратное арифметическое значение (например, если вы генерируете 37, тогда ваш результат будет включать как 37, так и -37). Затем вы можете случайным образом перемешать результат; так, например, если вы случайным образом сгенерируете [17, -84, 12], тогда ваш окончательный массив может быть [-12, 17, -84, -17, 84, 12].

. . . все это означает, что вам необходимо выяснить свои точные требования. Случайность - это сложно!

Случайность - это просто. Единообразие сложно. :-) Ни один из ответов не дает единообразия.

rici 22.09.2018 00:53

@rici: «Сложный» - это не противоположность «легкому», а «простому». Randomess сложен, потому что гораздо проще сделать что-то «случайное», чем убедиться, что это действительно то, что вы хотели. Люди обычно хотят чего-то более конкретного, чем просто "случайное", но не знают, как это сделать точным. (Вы упоминаете единообразие [в какой-то области]; еще одним распространенным неявным желанием является неповторение.)

ruakh 22.09.2018 02:40

Думаю, мы согласны с тем, что случайность - это просто. Как вы указали, сложно (что противоположно легкому) сформулировать точные требования. После того, как сформулированы, будет легче найти подходящее решение, но решение вполне может быть сложным. Алгоритмы, которые обеспечивают единообразную выборку с заменой или без замены по всей области решения, как правило, попадают в эту категорию. Случайный: :-)

rici 22.09.2018 02:55

Вот еще способ. Начните с нуля и разделите случайный элемент массива 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));

Спасибо за это решение :)

Iwona Hajczewska 22.09.2018 08:22

@IwonaHajczewska на самом деле, тестирование показывает, что ответ Йонаса Вильмса, похоже, дает числа от -100 до 100, которые, хотя и не являются однородными, с течением времени распределяются более равномерно, чем это решение. Я хотел бы больше узнать о том, как это происходит, но, в зависимости от ваших потребностей, вы, возможно, были более правы, выбрав этот ответ.

גלעד ברקן 22.09.2018 14:57

@ גלעדברקן: "Не единообразно" в каком домене? Требование OP о том, что сумма чисел равна нулю, означает, что следует ожидать некоторого смещения в сторону нуля, поскольку оно исключает такие массивы, как [max, max, max, max] и [min, min, min, min], но допускает такие массивы, как [0 , 0, 0, 0]. У вашего решения также есть такая предвзятость, потому что ваш split всегда разрешает [0, n], но не всегда разрешает [max, n - max] или [min, n - min]. Не уверен, что это плохо.

ruakh 22.09.2018 16:51

@ruakh Спасибо за комментарий. Я не совсем понимаю, что вы имеете в виду, говоря о split - он всегда позволяет выбрать случайное число в максимально возможном диапазоне (например, (low, high) for -98 => [-100, 2]; (low, high) for 67 => [-33, 100].

גלעד ברקן 22.09.2018 16:59

@ רקן: Я имею в виду, что "максимальный диапазон, который он может иметь" по своей природе будет смещен в сторону нуля, поскольку этот диапазон будет включать 0 для всех значений n, будет включать 1 для 99,5% таких значений, будет включать 2 для 99 % из них и т. д., но будет включать 100 только для 50% значений.

ruakh 22.09.2018 22:48
Ответ принят как подходящий

Это мое решение, в основном вы выполняете цикл 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;
}

Другие вопросы по теме