Создание случайных чисел, которые при сложении равны указанному числу

Я пытаюсь получить четыре случайных числа от 0 до 100, которые будут равны 100.

Мне удалось добиться результата, но он неэффективен. Мой метод просто продолжает цикл случайных чисел от 0 до 100, затем добавляет их, если он не равен 100, то повторяет процесс, пока не станет равно 100. Есть ли более эффективный метод?

заранее спасибо


person almost a beginner    schedule 16.04.2015    source источник
comment
Покажите нам свой код.   -  person spongebob    schedule 16.04.2015
comment
попробуйте разделять и побеждать: как бы вы получили два числа, которые в сумме дают 100? могли бы вы получить два числа, которые доходят до случайно выбранного числа от 0 до 100?   -  person BeyelerStudios    schedule 16.04.2015
comment
Разве вы не можете сгенерировать первые три, а четвертый сделать 100?   -  person Slate    schedule 16.04.2015
comment
@kjhf что, если сумма первых трех чисел больше 100?   -  person BeyelerStudios    schedule 16.04.2015
comment
Также можно использовать случайные пропорции. Вы начинаете со 100 и делите его на две части, используя случайное число, чтобы узнать, насколько велико одно из чисел по сравнению с другим. Затем продолжайте разделять одно из этих двух, пока не достигнете желаемого количества случайных чисел.   -  person Claudio    schedule 16.04.2015
comment
Не могли бы вы добавить пример кода того, что у вас уже есть, и расширить то, что вы собираетесь делать, я не думаю, что я не могу быть единственным, кто немного заблудился в этом вопросе. Цель состоит в том, чтобы бросать 100-гранный кубик снова и снова и подсчитывать, сколько раз он наберет 100?   -  person Felype    schedule 16.04.2015


Ответы (5)


Вы можете сгенерировать первое случайное число от 1 до (100-3). Предположим, ваше первое случайное число - X. Следующее случайное число, которое вы сгенерируете, должно быть между X и (100-2). Предположим, что это число Y. Следующее случайное число должно быть между (X + Y) и (100-1). Предположим, что это число Z.

Теперь у вас есть четвертое случайное число - 100-X-Y-Z. Дважды проверьте несколько из них, чтобы убедиться, что он имеет то же распределение, что и ваш текущий генератор чисел, чтобы проверить свою работу.

person Carlos Bribiescas    schedule 16.04.2015
comment
Это не приведет к тому же распределению. - person fabian; 16.04.2015
comment
Я думаю, что так и будет. Это в основном логика, которую вы могли бы написать после того, как сгенерировали все 4 числа, чтобы убедиться, что она работает. Вы можете объяснить, почему вы так думаете? - person Carlos Bribiescas; 16.04.2015
comment
Звучит хорошо, каждая следующая итерация увеличивает шанс достичь 100, может привести к более низкому диапазону возможных результатов, не уверен, что это намеревается OP, я действительно не понимаю вопрос. - person Felype; 16.04.2015
comment
Исходный алгоритм: очевидно, такая же вероятность появления 1 и третьего числа. Ваш алгоритм: 1 / 97 шанс 1 в качестве первого элемента и отсутствие шанса 1 в качестве третьего числа. - person fabian; 16.04.2015
comment
Вы пытаетесь сказать, что числа, соответствующие этому ограничению, будут иметь то же распределение, что и исходное распределение. Это неправда. Эти числа генерируются из исходного распределения, но затем вы выбрасываете кучу комбинаций, которые не работают. Таким образом, распределение отличается от исходного распределения из-за ограничений. Конечно, в исходном алгоритме 1 может произойти где угодно, но многие из них будут отброшены. Что меняет раздачу. - person Carlos Bribiescas; 16.04.2015
comment
Представьте, что вы сгенерировали его оригинальным способом. Вы можете отсортировать числа, а затем применить мой алгоритм, чтобы определить, будет ли комбинация работать или нет. Правильно? Оригинал просто генерирует лишние случайные числа без надобности, в то время как это сокращает его по мере продвижения. - person Carlos Bribiescas; 16.04.2015
comment
Я искал только четыре псевдослучайных числа, которые в сумме дают 100, я не ожидал какого-либо продвинутого алгоритма равномерного распределения, который, вероятно, займет у меня некоторое время, чтобы научиться. Я выбрал этот ответ, потому что: 1. он работает, 2. он объяснен так, как я могу понять. Спасибо тем, кто код хорошо залил. - person almost a beginner; 16.04.2015

Нарисуйте 3 числа от 0 до 100 в случайном порядке без повторения. Теперь отсортируйте их по возрастанию и интерпретируйте промежутки между последующими числами как числа, которые вы бы нарисовали в первую очередь. При использовании 3-х разделителей есть 4 пробела для 4 чисел, которые вы хотите нарисовать.

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

person SpaceTrucker    schedule 16.04.2015
comment
Просто и элегантно - могут быть альтернативы сортировке, например, Math.min и Math.max. - person OldCurmudgeon; 16.04.2015

Ты можешь это сделать :

Random r = new Random();
int n1 = r.nextInt(100);
int n2 = r.nextInt(100 - n1);
int n3 = r.nextInt(100 - n1 - n2);
int n4 = 100 - n1 - n2 - n3;
person Oussama Zoghlami    schedule 16.04.2015
comment
Если ваше первое число 99, это не сработает. - person Carlos Bribiescas; 16.04.2015
comment
Граница, переданная в nextInt(), является эксклюзивной. Вам нужно будет использовать 101. - person Sean Bright; 16.04.2015
comment
@CarlosBribiescas: почему, если вы получите 99 в качестве первого числа, это не сработает? вы получите числа от 0 до 1? - person Oussama Zoghlami; 16.04.2015
comment
Ой, я не понимал, что 0 - допустимое число. - person Carlos Bribiescas; 16.04.2015
comment
Если 0 действителен, значит, должно быть 100. Таким образом, вам нужно будет использовать r.nextInt(101); для поиска n1. Затем, если n1 = 100, код выдаст IllegalArgumentException, поскольку r.nextInt(0); (100 - 100 = 0) недопустим. - person Tobold; 16.04.2015
comment
Вот почему я бы поставил r.nextInt(100) в начале - person Oussama Zoghlami; 16.04.2015
comment
Ах да, ты прав. - person Tobold; 16.04.2015

Кажется, это хорошо работает:

Random random = new Random();

public int[] fourRandoms(int limit) {
    int[] randoms = new int[4];

    int[] three = new int[3];
    for (int i = 0; i < 3; i++) {
        three[i] = random.nextInt(limit);
    }

    int min = Math.min(three[0], Math.min(three[1], three[2]));
    int max = Math.max(three[0], Math.max(three[1], three[2]));
    int mid = three[0] + three[1] + three[2] - max - min;

    randoms[0] = min - 0;
    randoms[1] = mid - min;
    randoms[2] = max - mid;
    randoms[3] = limit - max;

    return randoms;
}

public void test() {
    for (int i = 1; i < 10; i++) {
        int[] randoms = fourRandoms(100);
        int sum = Arrays.stream(randoms).sum();
        System.out.println(Arrays.toString(randoms) + " = " + sum);
    }
}

Это реализация идеи @ SpaceTrucker.

Как вариант - с помощью Java 8 Streams.

public int[] nRandomsThatSumToLimit(int n, int limit) {
    return IntStream
            .concat(
                    // Stream n-1 random ints and sort them.
                    random.ints(n - 1, 0, limit).sorted(),
                    // Plus the final limit value.
                    IntStream.of(limit))
            // Convert into a stream of differences.
            .map(new IntUnaryOperator() {
                // Maintain the previous.
                int p = 0;

                @Override
                public int applyAsInt(int n) {
                    // Difference.
                    int d = n - p;
                    // Persist.
                    p = n;
                    return d;
                }
            }).toArray();
}
person OldCurmudgeon    schedule 16.04.2015
comment
Мне очень нравится решение Streams! Вы сами это придумали, @OldCurmudgeon? - person AndreasPizsa; 28.08.2018
comment
@AndreasPizsa - Спасибо. Извините, но я не могу вспомнить, откуда у меня возникла идея. Обратите внимание, это было 3 года назад. Однако если задуматься, это действительно кажется очевидным. Возьмите различия между случайными числами и убедитесь, что эти различия составляют определенное значение, сделав последнее целевым числом. - person OldCurmudgeon; 28.08.2018
comment
При дальнейшем изучении это на самом деле просто расширение идеи @ SpaceTrucker на n элементы, не так ли. - person OldCurmudgeon; 28.08.2018

Сгенерируйте 4 случайных числа от 0 до 100
Суммируйте четыре числа
Разделите каждое из четырех сгенерированных чисел на s / 100 (с округлением)
Теперь ваша сумма будет 99, 100, 101 < br> При необходимости отрегулируйте одно из случайных чисел вверх или вниз на единицу, убедившись, что корректировка не опускается ниже 0 или выше 100

person user2304484    schedule 16.04.2015