Генерируйте серию случайных чисел, которые составляют в целом N в c#

Это легко сделать.

$(".action-complete-task").on('click', function(event){
  if($(this).hasClass('action-2')){
    //Do action 2
  }else{
    //Do action 1
  }
})
15
задан mmcdole 23 January 2009 в 05:48
поделиться

15 ответов

Я не уверен, что статистические данные находятся на этом, но, проблема здесь - то, что Вы не хотите случайным образом выбирать число, которое лишает возможности суммировать N с количеством M записей или путем промаха или недостаточного подъема. Вот то, как я сделал бы это:

static void Main()
{
    int count = 30;
    int[] numbers = getNumbers(count, 155);
    for (int index = 0; index < count; index++)
    {
        Console.Write(numbers[index]);
        if ((index + 1) % 10 == 0)
            Console.WriteLine("");
        else if (index != count - 1)
            Console.Write(",");
    }
    Console.ReadKey();
}
static int[] getNumbers(int count, int total)
{
    const int LOWERBOUND = 1;
    const int UPPERBOUND = 9;

    int[] result = new int[count];
    int currentsum = 0;
    int low, high, calc;

    if((UPPERBOUND * count) < total ||
        (LOWERBOUND * count) > total ||
        UPPERBOUND < LOWERBOUND)
        throw new Exception("Not possible.");

    Random rnd = new Random();

    for (int index = 0; index < count; index++)
    {
        calc = (total - currentsum) - (UPPERBOUND * (count - 1 - index));
        low = calc < LOWERBOUND ? LOWERBOUND : calc;
        calc = (total - currentsum) - (LOWERBOUND * (count - 1 - index));
        high = calc > UPPERBOUND ? UPPERBOUND : calc;

        result[index] = rnd.Next(low, high + 1);

        currentsum += result[index];
    }

    // The tail numbers will tend to drift higher or lower so we should shuffle to compensate somewhat.

    int shuffleCount = rnd.Next(count * 5, count * 10);
    while (shuffleCount-- > 0)
        swap(ref result[rnd.Next(0, count)], ref result[rnd.Next(0, count)]);

    return result;
}
public static void swap(ref int item1, ref int item2)
{
    int temp = item1;
    item1 = item2;
    item2 = temp;
}

У меня не было большого количества времени для тестирования этого так извинения, если существует дефект в моей логике где-нибудь.

Править:

Я сделал некоторое тестирование, и все кажется твердым. Если Вы хотите хорошее симпатичное распространение, похоже на желание чего-то вроде Total = Count * ((UPPER + LOWER) / 2). Хотя я вполне уверен что как различие между UPPER и LOWER увеличивает более гибкое, которым это становится.

10
ответ дан 1 December 2019 в 02:47
поделиться
public static List<int> getNumbers(int n)
    {
        Random random = new Random(DateTime.Now.Millisecond);
        List<int> obtainedNumbers = new List<int>(); 
        do
        {
            obtainedNumbers.Add(random.Next(1, 9));
        }
        while (n - obtainedNumbers.Sum() > 0);
        return obtainedNumbers;
    }

Коду JaredPar нравлюсь я, но его медленное, он похож, чтобы бросить монету и надеяться получить значение n. Хорошие части кодов

-1
ответ дан 1 December 2019 в 02:47
поделиться

Я думал, что попробую деление и завоюю подход. Это, кажется, работает вполне прилично. Я уверен, что результаты не действительно случайны из-за элементов ограничения алгоритма, но он приближается. По существу я разделил список в два и целевую сумму в половине и рекурсивно вызываю, пока я не получаю списки 3 элементов или меньше. Затем я использую повторение грубой силы случайных цифр, пока эти меньшие суммы не достигнуты. Вот код с образцом, выполненным ниже его.

using System;
using System.Collections.Generic;

namespace AddUpClient {
    class Program {

        static void Main() {
            AddUpWorker worker = new AddUpWorker();
            int MinDigit = 1;
            int MaxDigit = 9;
            int ItemsToSum = 30;
            int TargetSum = 150;

            try {
                //Attempt to get a list of pseudo-random list of integers that add up to the target sum
                IList<int> Results = worker.AddUp(MinDigit, MaxDigit, ItemsToSum, TargetSum);

                EvaluateResults(TargetSum, Results);
                Console.ReadLine();
            }
            catch (Exception E) {
                Console.Out.WriteLine("Error: {0}", E.Message);
                return;
            }

        }

        private static void EvaluateResults(int TargetSum, IList<int> Results)
        {
            Console.Out.WriteLine("Results have {0} items.", Results.Count);

            int Sum = 0;
            foreach (int Result in Results) {
                Sum += Result;
                Console.Out.WriteLine("Result: {0} Running total: {1}", Result, Sum);
            }
            Console.Out.WriteLine();
            Console.Out.WriteLine("Result = {0}", (Sum == TargetSum ? "SUCCESS" : "FAIL"));
        }
    }

    internal class AddUpWorker {

        Random RGenerator = new Random();

        public IList<int> AddUp(int MinDigit, int MaxDigit, int ItemsToSum, int TargetSum) {

            Console.Out.WriteLine("AddUp called to sum {0} items to get {1}", ItemsToSum, TargetSum);
            if (ItemsToSum > 3) {

                int LeftItemsToSum = ItemsToSum/2;
                int RightItemsToSum = ItemsToSum - LeftItemsToSum;

                int LeftTargetSum = TargetSum/2;
                int RightTargetSum = TargetSum - LeftTargetSum;


                IList<int> LeftList = AddUp(MinDigit, MaxDigit, LeftItemsToSum, LeftTargetSum);
                IList<int> RightList = AddUp(MinDigit, MaxDigit, RightItemsToSum, RightTargetSum);

                List<int> Results = new List<int>();
                Results.AddRange(LeftList);
                Results.AddRange(RightList);
                return Results;
            }

            // 3 or less

            int MinSumWeCanAchieve = ItemsToSum*MinDigit;
            int MaxSumWeCanAchieve = ItemsToSum*MaxDigit;


            if (TargetSum < MinSumWeCanAchieve)
                throw new ApplicationException("We added up too fast");

            if (TargetSum > MaxSumWeCanAchieve)
                throw new ApplicationException("We added up too slow");

            //Now we know we can achieve the result -- but it may not be too efficient...

            int[] TrialNumbers = new int[ItemsToSum];
            int MaxIteration = 100000;
            int IterationPrintInterval = 1000;
            int TrialSum;
            bool PrintIteration;

            for (int Iteration = 1; Iteration <= MaxIteration; ++Iteration) {

                PrintIteration = ((Iteration % IterationPrintInterval) == 0);

                if (PrintIteration)
                    Console.Out.WriteLine("Iteration {0} attempting to sum {1} numbers to {2}",
                        Iteration, ItemsToSum, TargetSum);

                TrialSum = 0;
                for (int j=0; j < ItemsToSum; ++j) {
                    TrialNumbers[j] = RGenerator.Next(MinDigit, MaxDigit + 1);
                    TrialSum += TrialNumbers[j];
                }
                if (PrintIteration)
                    ShowArray(string.Format("Iteration: {0}", Iteration), TrialNumbers);

                if (TrialSum == TargetSum) {    //Yay
                    ShowArray(string.Format("Success in {0} iterations: ", Iteration), TrialNumbers);
                    return new List<int>(TrialNumbers);
                }
                //try again....
            }

            throw new ApplicationException(string.Format("Maximum of {0} trials exceeded", MaxIteration));
        }

        private void ShowArray(string Prefix, int[] numbers)
        {
            for (int i = 0; i < numbers.Length; ++i) {
                if (i == 0)
                    Console.Write("{0} {1}", Prefix, numbers[i]);
                else
                    Console.Write(", {0}", numbers[i]);
            }
            Console.WriteLine();
        }
    }
}

AddUp called to sum 30 items to get 150
AddUp called to sum 15 items to get 75
AddUp called to sum 7 items to get 37
AddUp called to sum 3 items to get 18
Success in 10 iterations:  7, 2, 9
AddUp called to sum 4 items to get 19
AddUp called to sum 2 items to get 9
Success in 12 iterations:  5, 4
AddUp called to sum 2 items to get 10
Success in 2 iterations:  1, 9
AddUp called to sum 8 items to get 38
AddUp called to sum 4 items to get 19
AddUp called to sum 2 items to get 9
Success in 11 iterations:  4, 5
AddUp called to sum 2 items to get 10
Success in 6 iterations:  8, 2
AddUp called to sum 4 items to get 19
AddUp called to sum 2 items to get 9
Success in 3 iterations:  8, 1
AddUp called to sum 2 items to get 10
Success in 1 iterations:  4, 6
AddUp called to sum 15 items to get 75
AddUp called to sum 7 items to get 37
AddUp called to sum 3 items to get 18
Success in 3 iterations:  4, 6, 8
AddUp called to sum 4 items to get 19
AddUp called to sum 2 items to get 9
Success in 17 iterations:  3, 6
AddUp called to sum 2 items to get 10
Success in 24 iterations:  1, 9
AddUp called to sum 8 items to get 38
AddUp called to sum 4 items to get 19
AddUp called to sum 2 items to get 9
Success in 3 iterations:  2, 7
AddUp called to sum 2 items to get 10
Success in 3 iterations:  1, 9
AddUp called to sum 4 items to get 19
AddUp called to sum 2 items to get 9
Success in 4 iterations:  5, 4
AddUp called to sum 2 items to get 10
Success in 2 iterations:  9, 1
Results have 30 items.
Result: 7 Running total: 7
Result: 2 Running total: 9
Result: 9 Running total: 18
Result: 5 Running total: 23
Result: 4 Running total: 27
Result: 1 Running total: 28
Result: 9 Running total: 37
Result: 4 Running total: 41
Result: 5 Running total: 46
Result: 8 Running total: 54
Result: 2 Running total: 56
Result: 8 Running total: 64
Result: 1 Running total: 65
Result: 4 Running total: 69
Result: 6 Running total: 75
Result: 4 Running total: 79
Result: 6 Running total: 85
Result: 8 Running total: 93
Result: 3 Running total: 96
Result: 6 Running total: 102
Result: 1 Running total: 103
Result: 9 Running total: 112
Result: 2 Running total: 114
Result: 7 Running total: 121
Result: 1 Running total: 122
Result: 9 Running total: 131
Result: 5 Running total: 136
Result: 4 Running total: 140
Result: 9 Running total: 149
Result: 1 Running total: 150

Result = SUCCESS
0
ответ дан 1 December 2019 в 02:47
поделиться

Чтобы иметь ответ, не склонявший к меньшим числам (или любая другая предвзятость), Вы идеально генерировали бы все возможные наборы чисел, которые составляют в целом N. После того, как у Вас будут все наборы, случайным образом выберите один из наборов. После выбора набора победы можно случайным образом встряхнуть порядок чисел в том наборе в случае необходимости.

0
ответ дан 1 December 2019 в 02:47
поделиться

Этот метод возвратит 30 случайных чисел, которые составляют в целом arbitraryN. Это возможно, делают, чтобы иметь приблизительно 0 значений. если это не выполнимо, просто инициализируйте массив все к и если сумма больше к arbitraryN, vals[nextIdx] набора к 1 вместо 0.Надеюсь, это поможет.

    private int[] getNumbers(int arbitraryN) {
        int[] vals = new int[30];
        int nextIdx = 0;
        int nextNumber=0;
        Random r = new Random();
        if (arbitraryN > 270 || arbitraryN < 30)
            throw new Exception("Not a Valid number");
        while (vals.Sum() < arbitraryN)
        {
            nextNumber = r.Next(1, 9);
            nextIdx = r.Next(29);
            vals[nextIdx] = nextNumber;
            if (vals.Sum() > arbitraryN)
            {
                vals[nextIdx] = 0;
                vals[nextIdx] = 270 - vals.Sum();
                break;
            }
        }
        return vals;
    }
0
ответ дан 1 December 2019 в 02:47
поделиться

Если Вы хотите несмещенный алгоритм затем, наивная реализация - что-то как:

while (true) {
  numbers = [];
  total = 0;
  for (i = 0; i < COUNT; ++i) {
    next = rand(BOUNDS);
    total += next;
    numbers.push(next);
  }

  if (total == TARGET) {
    return numbers;
  }
}

Это не завершается и медленное, но это не смещается. Если Вы хотите несмещенный алгоритм, я не убежден, что алгоритмы, отправленные здесь, несмещенные.

0
ответ дан 1 December 2019 в 02:47
поделиться

Я думаю, что это - самый простой способ сделать это, таким образом, это может испытать недостаток в некоторой изощренности однако, это получит Вас там.

        String output = "";
        int sum = 0;
        int result = 200;       //enter the "end number"

        Random r = new Random();

        while (sum != result) {
            int add;
            if ((result - sum) > 10)
            {
                add = r.Next(1, 10);
            }
            else
            {
                add = r.Next(result - sum + 1);
            }

            sum += add;
            output += add.ToString() + " + ";
        }

        output = output.Remove(output.Length - 2);

        Console.WriteLine(output);

Надежда это помогает!

0
ответ дан 1 December 2019 в 02:47
поделиться

Алгоритм:

  1. Общее количество набора = 200 (или безотносительно)
  2. Генерируйте Случайное число между 1-9
  3. Проверьте если (общее количество - newRandomNumber> = 0), если никакой goto 6
  4. общее количество - = newRandomNumber
  5. Добавьте newRandomNumber для выстраивания, goto 2.
  6. newRandomNumber = общее количество
  7. Добавьте newRandomNumber, чтобы выстроить если newRandomNumber! = 0
  8. Конец
0
ответ дан 1 December 2019 в 02:47
поделиться

Нет никакого guarrentee, что 30 случайных чисел от 1-9 составили бы в целом любой определенный N.

То, что можно найти, является списком чисел, которые составят в целом N и ограничены от 1-9, но число не будет 30 обязательно. Я верю минимальному количеству чисел, в которых Вы нуждаетесь, 23, будучи (22*9) + 2. Максимум, конечно, будет 200 (200*1). Таким образом, длина списка где-нибудь внутренняя [23,200]. Возможности, что случайный список может быть длиной 30, являются таким образом довольно низкими. Если все длины списка доступны (я думаю, что они), Ваши возможности в конечном счете на уровне приблизительно 0,5%.

0
ответ дан 1 December 2019 в 02:47
поделиться

Эта программа попытается дать Вам ответ. Но потому что Вы имеете дело со случайными числами, существует возможность, что это никогда не будет давать Вам ответ.

public static IEnumerable<int> GetRandom()
{
    var rand = new Random();
    while (true)
    {
        yield return
        rand.Next(1, 9);
    }
}

public static List<int> GetThirtyThatAddToTwoHundred()
{
    do
    {
        var current = GetRandom().Take(30);
        if (200 == current.Sum())
        {
            return current.ToList();
        }
    } while (true);
}
3
ответ дан 1 December 2019 в 02:47
поделиться

Мой исходный оператор:

Можно только генерировать 29 случайных чисел. 30-е число будет определено другими 29 и суммой. Это статистически важно...

Я хотел добавить некоторое разъяснение после размышления об этом и проверки с помощью ping-запросов сообщества...

Я теперь полагаю, что мой исходный оператор ложь. Это было слишком снисходительно (который lc, на который указывают). Вы не можете даже генерировать 29 действительно случайных чисел. Поскольку Вы становитесь ближе и ближе к 30, заключительные цифры не случайны тот же путь который rnd [1.. 9] случайно. lc пытался смягчить это для предложения решения, но я верю решению, которое он предложил (и Spencer) отвечает на совсем другой вопрос. Тот вопрос "Всех наборов 30 цифр между 1 и 9, которые составляют в целом 200, создают тот случайным образом".

То, чему я верю для имения место, - то, что вопрос, как указано неразрешим, которому я верю, может быть доказан с Принципом Ящика (также используемый Knuth, чтобы показать, что определенные "случайные" перестановки не были действительно случайны), но я не сделал математики.

Хороший разговор все.

4
ответ дан 1 December 2019 в 02:47
поделиться

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

public static List<int> RandomListByIncrementing(int digitMin, int digitMax, 
                                                 int targetSum, int numDigits)
{
    if(targetSum < digitMin * numDigits || targetSum > digitMax * numDigits)
        throw new ArgumentException("Impossible!", "targetSum");

    List<int> ret = new List<int>(Enumerable.Repeat(digitMin, numDigits));
    List<int> indexList = new List<int>(Enumerable.Range(0, numDigits-1));

    Random random = new Random();
    int index;

    for(int currentSum=numDigits * digitMin; currentSum<targetSum; currentSum++)
    {
        //choose a random digit in the list to increase by 1
        index = random.Next(0,indexList.Length-1);

        if(++ret[indexList[index]] == digitMax)
        {
            //if you've increased it up to the max, remove its reference
            //because you can't increase it anymore
            indexList.RemoveAt(index);
        }
    }

    return ret;
}

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

Теперь нет никакого бизнеса перестановки, который будет сделан в конце дня, хотя возможно это все еще произведет один из доступных наборов ответов на вопрос, и это - вопрос, которого "чувствует себя лучше" или быстрее для выполнения.

1
ответ дан 1 December 2019 в 02:47
поделиться

Если статистическая предвзятость от истинной случайности приемлема, можно добавить числа до N - [макс. случайное число], затем выбрать последнее число как N - сумма (выбранный до сих пор).

0
ответ дан 1 December 2019 в 02:47
поделиться

Проблема, мы хотим, чтобы все числа были ограничены 1-9 и составили в целом N. Таким образом, мы должны генерировать каждое число один за другим и определить реальные границы для следующего числа.

Это, конечно, генерирует статистическую предвзятость к концу списка, таким образом, я рекомендую переставить массив однажды после генерации.

Для определения границ следующего числа сделайте следующее: Верхняя граница = берет остающуюся сумму минус (число элементов, остающееся * минута). Нижняя граница = берет остающуюся сумму минус (число элементов, остающееся * макс.).

Что-то как (непротестированный):

public static List<int> RandomList(int digitMin, int digitMax, 
                                   int targetSum, int numDigits)
{
    List<int> ret = new List<int>(numDigits);

    Random random = new Random();
    int localMin, localMax, nextDigit;
    int remainingSum = targetSum;

    for(int i=1; i<=numDigits; i++)
    {
          localMax = remainingSum - ((numDigits - i) * min);
          if(localMax > max)
              localMax = max;

          localMin = remainingSum - ((length - i) * max);
          if(localMin > min)
              localMin = min;

          nextDigit = random.Next(localMin, localMax);
          ret.Add(nextDigit);
          remainingSum -= nextDigit;
    }

    return ret;
}

Идея здесь состоит в том, поскольку Вы генерируете числа, диапазон возможных значений для остающихся чисел становится меньшим, как предельная функция, обнуляющая в на целевой сумме. Вид.

Править: Я должен был измениться, чтобы цикл был на основе 1, потому что мы хотим число элементов, оставленное ПОСЛЕ генерации этого.

Edit2: Поместите его в метод для полноты и измененный length быть numDigits для удобочитаемости.

7
ответ дан 1 December 2019 в 02:47
поделиться

Поэтому я должен спросить: Есть ли у этого настоящая цель, или это просто упражнение или домашнее задание? Ведется большая работа по предотвращению «предвзятости». Это актуальное требование или подойдет какое-нибудь довольно случайное решение? Не зная требований, действительно легко потерять много времени. Если это реальная проблема, объясните, каковы фактические требования.

1
ответ дан 1 December 2019 в 02:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: