Из 5 бросков кубиков сгенерируйте случайное число в диапазоне [1–100].

Я выполнял некоторые упражнения по кодированию, и у меня возникли проблемы с этим вопросом:

Из 5 бросков кубиков (6-сторонних) сгенерируйте случайное число в диапазоне [1 - 100].

Я реализовал следующий метод, но возвращаемое число не является случайным (функция вызывается 1000000 раз, и несколько чисел никогда не отображаются в диапазоне от 1 до 100).

public static int generator() {

     Random rand = new Random();
     int dices = 0;

     for(int i = 0; i < 5; i++) {
         dices += rand.nextInt(6) + 1;
     }

     int originalStart = 5;
     int originalEnd = 30;
     int newStart = 1;
     int newEnd = 100;

     double scale = (double) (newEnd - newStart) / (originalEnd - originalStart);
     return (int) (newStart + ((dices - originalStart) * scale));
}

person yohm    schedule 03.09.2014    source источник
comment
Не создавайте каждый раз новый экземпляр Random, поддерживайте единственный экземпляр для каждого вызова метода. Хотя вы все еще можете потерять числа, диапазон будет гораздо более случайным.   -  person MadProgrammer    schedule 04.09.2014
comment
просто используйте первый бросок кубика. Он вернет случайное число от 1 до 100. Это или просьба уточнить свой вопрос.   -  person djechlin    schedule 04.09.2014
comment
ему нужно имитировать броски игральных костей. Когда вы в последний раз видели игральные кости с 99 гранями?   -  person Slavic    schedule 04.09.2014
comment
Я раньше видел кубик со 100 гранями.   -  person David Conrad    schedule 04.09.2014
comment
@ Славянские к сожалению, они существуют   -  person JSlain    schedule 04.09.2014


Ответы (3)


Итак, 5 бросков кубиков, каждый с 6 вариантами. если они не заказаны, у вас будет диапазон от 5 до 30, как упоминалось выше - никогда не хватит для 1–100.

Вам нужно принять заказ, это дает вам шкалу 1,1,1,1,1 - 6,6,6,6,6 (база 6), предполагая значение 1 -> 0, у вас есть база из 5 цифр 6 число сгенерировано. Как мы все знаем, 6 ^ 5 = 7776 уникальных возможностей. ;)

Для этого я собираюсь дать вам предвзятое случайное решение.

int total = 0;
int[] diceRolls;
for (int roll : diceRolls) {
    total = total*6 + roll - 1;
}

return total % 100 + 1;

Спасибо JosEdu за разъяснение требований к скобкам

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

person Guy Flavell    schedule 04.09.2014
comment
Забавно похожий на ответ славян, который он, должно быть, писал в то же время, что и я, только я использую целые числа, а не десятичные. :) - person Guy Flavell; 04.09.2014
comment
Скобки не нужны, оператор% имеет приоритет перед +. - person JosEduSol; 04.09.2014

Проблема в том, что в 5-30 не хватает случайных значений для сопоставления один к одному с интервалом 1-100. Это означает, что определенным ценностям суждено никогда не проявиться; количество этих «потерянных» значений зависит от соотношения размеров двух интервалов.

Однако вы можете использовать силу своих игральных костей более эффективным способом. Вот как бы я это сделал:

Подход 1

  1. Используйте результат первой кости, чтобы выбрать один подынтервал из 6 равных подынтервалов размером 16,5 (99/6).
  2. Используйте результат второй кости, чтобы выбрать один подынтервал из 6 равных подынтервалов подынтервала, который вы выбрали на первом шаге.
  3. Используйте ... Я думаю, вы знаете, что будет дальше.

Подход 2

Постройте свое случайное число, используя цифры в системе с основанием 6. I.E. Первый кубик будет первой цифрой числа с основанием 6, второй кубик - второй цифрой и т. Д.
Затем преобразовать в основание 10 и разделить на (46656/99). У вас должно быть случайное число. На самом деле вы могли бы использовать только 3 кубика, остальные два просто лишние.

person Slavic    schedule 04.09.2014
comment
Почему нет? Шансы на присутствие любого числа от 1 до 100 равны. По крайней мере, мне так кажется сейчас. - person Slavic; 04.09.2014
comment
вам придется взять функцию пола, и интервалы, на которые вы в конечном итоге нарезаете, не будут располагаться равномерно по отношению к строкам между целыми числами. Попробуйте написать галочки 3,6,9,12,15 ... в строке, затем отметьте 2,4,6,8, ... и вы поймете, что я имею в виду. - person djechlin; 04.09.2014
comment
Или, если точнее, любая комбинация целых чисел (a, b, c, d, e, f) - ›число от 1 до 100. Вы действительно думаете, что сможете делать это равномерно? Нет; это то же самое, что и исходная математическая задача, а подход с плавающей запятой - это просто обходной путь для вычислений. - person djechlin; 04.09.2014

Прокатка шестигранной матрицы 5 раз дает 6 ^ 5 = 7776 возможных последовательностей, причем все они равновероятны. В идеале вам нужно разделить эти последовательности на 100 групп равного размера, и у вас будет свой номер [1 - 100], но, поскольку 7776 не делится на 100 без остатка, это невозможно. Лучшее, что вы можете сделать, чтобы минимизировать смещение, - это 76 групп, сопоставленных по 78 последовательностей каждая, и 24 группы, сопоставленные с 77 последовательностями каждая. Закодируйте (упорядоченные) броски кубиков как число n с основанием 6 и верните 1 + (n% 100).

Мало того, что нет способа удалить смещение с помощью 5 бросков кубиков, нет такого количества бросков кубиков, которое полностью устранит смещение. Не существует значения k, для которого 6 ^ k делится на 100 без остатка (рассмотрим факторизации на простые множители). Это не означает, что нет способа устранить смещение, это просто означает, что вы не можете удалить смещение, используя процедуру, которая гарантированно завершится после любого определенного количества бросков кубиков. Но вы могли бы, например, сделать 3 броска костей, создавая 6 ^ 3 = 216 последовательностей, закодированных как число n с основанием 6, и вернуть 1 + (n% 100), если n ‹200. Уловка в том, что если n> = 200, вы должны повторите процедуру, и продолжайте повторять, пока не получите n <200. Таким образом, нет предвзятости, но также нет ограничений на то, как долго вы можете застрять в цикле. Но поскольку вероятность повторения составляет всего 16/216 каждый раз, с практической точки зрения это не проблема.

person JSLigon    schedule 20.03.2015