Как выбрать случайное число от 1 до 10

Автор оригинала: Ben Torvaney
  • Перевод
Представьте, что вам нужно сгенерировать равномерно распределённое случайное число от 1 до 10. То есть целое число от 1 до 10 включительно, с равной вероятностью (10%) появления каждого. Но, скажем, без доступа к монетам, компьютерам, радиоактивному материалу или другим подобным источникам (псевдо) случайных чисел. У вас есть только комната с людьми.

Предположим, что в этой комнате чуть более 8500 студентов.

Самое простое — попросить кого-нибудь: «Эй, выбери случайное число от одного до десяти!». Человек отвечает: «Семь!». Отлично! Теперь у вас есть число. Однако вы начинаете задаваться вопросом, является ли оно равномерно распределённым?

Поэтому вы решили спросить ещё несколько человек. Вы продолжаете их спрашивать и считать их ответы, округляя дробные числа и игнорируя тех, кто думает, что диапазон от 1 до 10 включает 0. В конце концов вы начинаете видеть, что распределение вообще не равномерное:

library(tidyverse)

probabilities <-
  read_csv("https://git.io/fjoZ2") %>%
  count(outcome = round(pick_a_random_number_from_1_10)) %>%
  filter(!is.na(outcome),
         outcome != 0) %>%
  mutate(p = n / sum(n))

probabilities %>%
  ggplot(aes(x = outcome, y = p)) +
  geom_col(aes(fill = as.factor(outcome))) +
  scale_x_continuous(breaks = 1:10) +
  scale_y_continuous(labels = scales::percent_format(),
                     breaks = seq(0, 1, 0.05)) +
  scale_fill_discrete(h = c(120, 360)) +
  theme_minimal(base_family = "Roboto") +
  theme(legend.position = "none",
        panel.grid.major.x = element_blank(),
        panel.grid.minor.x = element_blank()) +
  labs(title = '"Pick a random number from 1-10"',
       subtitle = "Human RNG distribution",
       x = "",
       y = NULL,
       caption = "Source: https://www.reddit.com/r/dataisbeautiful/comments/acow6y/asking_over_8500_students_to_pick_a_random_number/")


Данные с Reddit

Вы хлопаете себя по лбу. Ну конечно, оно не будет случайным. В конце концов, нельзя доверять людям.

Итак, что делать?


Вот бы найти какую-то функцию, которая преобразует распределение «человеческого ГСЧ» в равномерное распределение…

Интуиция тут относительно проста. Нужно всего лишь взять массу распределения оттуда, где она выше 10%, и переместить туда, где она меньше 10%. Так, чтобы все столбцы на графике были одного уровня:



По идее, такая функция должна существовать. Фактически, должно быть много различных функций (для перестановки). В крайнем случае, можно «разрезать» каждый столбец на бесконечно малые блоки и построить распределение любой формы (как кирпичики Lego).

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

Как найти такую функцию?


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

Линейное программирование (LP, также именуется линейной оптимизацией) — метод достижения наилучшего результата… в математической модели, требования которой представлены линейными отношениями… Стандартная форма представляет собой обычную и наиболее интуитивную форму описания задачи линейного программирования. Она состоит из трёх частей:

  • Линейная функция, которую необходимо максимизировать
  • Проблемные ограничения следующей формы
  • Неотрицательные переменные

Аналогично можно сформулировать и проблему перераспределения.

Представление проблемы


У нас есть набор переменных $(x_{i,j}$, каждая из которых кодирует долю вероятности, перераспределённую от целого числа $i$ (от 1 до 10) к целому числу $j$ (от 1 до 10). Поэтому, если $(x_{7,1} = 0.2$, то нам нужно перенести 20% ответов от семёрки к единице.

variables <-
  crossing(from = probabilities$outcome,
           to   = probabilities$outcome) %>%
  mutate(name = glue::glue("x({from},{to})"),
         ix = row_number())

variables

## # A tibble: 100 x 4
##     from    to name       ix
##    <dbl> <dbl> <glue>  <int>
##  1     1     1 x(1,1)      1
##  2     1     2 x(1,2)      2
##  3     1     3 x(1,3)      3
##  4     1     4 x(1,4)      4
##  5     1     5 x(1,5)      5
##  6     1     6 x(1,6)      6
##  7     1     7 x(1,7)      7
##  8     1     8 x(1,8)      8
##  9     1     9 x(1,9)      9
## 10     1    10 x(1,10)    10
## # … with 90 more rows

Мы хотим ограничить эти переменные таким образом, чтобы все перераспределённые вероятности суммировались в 10%. Другими словами, для каждого $j$ от 1 до 10:

$x_{1, j} + x_{2, j} + \ldots\ x_{10, j} = 0.1$


Можем представить эти ограничения в виде списка массивов в R. Позже свяжем их в матрицу.

fill_array <- function(indices,
                       weights,
                       dimensions = c(1, max(variables$ix))) {
  init <- array(0, dim = dimensions)

  if (length(weights) == 1) {
    weights <- rep_len(1, length(indices))
  }

  reduce2(indices, weights, function(a, i, v) {
    a[1, i] <- v
    a
  }, .init = init)
}

constrain_uniform_output <-
  probabilities %>%
  pmap(function(outcome, p, ...) {
    x <-
      variables %>%
      filter(to == outcome) %>%
      left_join(probabilities, by = c("from" = "outcome"))

    fill_array(x$ix, x$p)
  })

Мы также должны убедиться, что сохраняется вся масса вероятностей из исходного распределения. Так что для каждого $j$ в диапазоне от 1 до 10:

$x_{1, j} + x_{2, j} + \ldots\ x_{10, j} = 0.1$


one_hot <- partial(fill_array, weights = 1)

constrain_original_conserved <-
  probabilities %>%
  pmap(function(outcome, p, ...) {
    variables %>%
      filter(from == outcome) %>%
      pull(ix) %>%
      one_hot()
  })

Как уже говорилось, мы хотим максимизировать сохранение исходного распределения. Это наша цель (objective):

$maximise (x_{1, 1} + x_{2, 2} + \ldots\ x_{10, 10})$


maximise_original_distribution_reuse <-
  probabilities %>%
  pmap(function(outcome, p, ...) {
    variables %>%
      filter(from == outcome,
             to == outcome) %>%
      pull(ix) %>%
      one_hot()
  })

objective <- do.call(rbind, maximise_original_distribution_reuse) %>% colSums()


Затем передаём проблему солверу, например, пакету lpSolve в R, объединив созданные ограничения в одну матрицу:

# Make results reproducible...
set.seed(23756434)

solved <- lpSolve::lp(
  direction    = "max",
  objective.in = objective,
  const.mat    = do.call(rbind, c(constrain_original_conserved, constrain_uniform_output)),
  const.dir    = c(rep_len("==", length(constrain_original_conserved)),
                   rep_len("==", length(constrain_uniform_output))),
  const.rhs    = c(rep_len(1, length(constrain_original_conserved)),
                   rep_len(1 / nrow(probabilities), length(constrain_uniform_output)))
)

balanced_probabilities <-
  variables %>%
  mutate(p = solved$solution) %>%
  left_join(probabilities,
            by = c("from" = "outcome"),
            suffix = c("_redistributed", "_original"))

Возвращается следующее перераспределение:

library(gganimate)

redistribute_anim <-
  bind_rows(balanced_probabilities %>%
            mutate(key   = from,
                   state = "Before"),
            balanced_probabilities %>%
            mutate(key   = to,
                   state = "After")) %>%
  ggplot(aes(x = key, y = p_redistributed * p_original)) +
  geom_col(aes(fill = as.factor(from)),
           position = position_stack()) +
  scale_x_continuous(breaks = 1:10) +
  scale_y_continuous(labels = scales::percent_format(),
                     breaks = seq(0, 1, 0.05)) +
  scale_fill_discrete(h = c(120, 360)) +
  theme_minimal(base_family = "Roboto") +
  theme(legend.position = "none",
        panel.grid.major.x = element_blank(),
        panel.grid.minor.x = element_blank()) +
  labs(title = 'Balancing the "Human RNG distribution"',
       subtitle = "{closest_state}",
       x = "",
       y = NULL) +
  transition_states(
    state,
    transition_length = 4,
    state_length = 3
  ) +
  ease_aes('cubic-in-out')

animate(
  redistribute_anim,
  start_pause = 8,
  end_pause = 8
)



Отлично! Теперь у нас есть функция перераспределения. Давайте поближе посмотрим, как именно движется масса:

balanced_probabilities %>%
  ggplot(aes(x = from, y = to)) +
  geom_tile(aes(alpha = p_redistributed, fill = as.factor(from))) +
  geom_text(aes(label = ifelse(p_redistributed == 0, "", scales::percent(p_redistributed, 2)))) +
  scale_alpha_continuous(limits = c(0, 1), range = c(0, 1)) +
  scale_fill_discrete(h = c(120, 360)) +
  scale_x_continuous(breaks = 1:10) +
  scale_y_continuous(breaks = 1:10) +
  theme_minimal(base_family = "Roboto") +
  theme(panel.grid.minor = element_blank(),
        panel.grid.major = element_line(linetype = "dotted"),
        legend.position = "none") +
  labs(title = "Probability mass redistribution",
       x = "Original number",
       y = "Redistributed number")



Эта диаграмма говорит, что примерно в 8% случаев, когда кто-то называет восемь в качестве случайного числа, вам нужно воспринимать ответ как единицу. В остальных 92% случаев он остаётся восьмёркой.

Было бы довольно просто решить задачу, если бы у нас был доступ к генератору равномерно распределённых случайных чисел (от 0 до 1). Но у нас только комната, полная людей. К счастью, если вы готовы примириться с несколькими небольшими неточностями, то из людей можно сделать довольно хороший ГСЧ, не спрашивая более двух раз.

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

probabilities %>%
  transmute(number = outcome,
            probability = scales::percent(p))

## # A tibble: 10 x 2
##    number probability
##     <dbl> <chr>
##  1      1 3.4%
##  2      2 8.5%
##  3      3 10.0%
##  4      4 9.7%
##  5      5 12.2%
##  6      6 9.8%
##  7      7 28.1%
##  8      8 10.9%
##  9      9 5.4%
## 10     10 1.9%

Например, когда кто-то даёт нам восемь в качестве случайного числа, нужно определить, должна ли эта восьмёрка стать единицей или нет (вероятность 8%). Если мы спросим другого человека о случайном числе, то с вероятностью 8,5% он ответит «два». Так что если это второе число равно 2, мы знаем, что должны вернуть 1 как равномерно распределённое случайное число.

Распространив эту логику на все числа, получаем следующий алгоритм:

  • Спросить у человека случайное число, $n_1$.
  • $n_1 = 1, 2, 3, 4, 6, 9,$ или $ 10$:
    • Ваше случайное число $n_1$
  • Если $n_1 = 5$:
    • Спросить у другого человека случайное число ($n_2$)
    • Если $n_2 = 5$ (12.2%):
      • Ваше случайное число 2
    • Если $n_2 = 10$ (1.9%):
      • Ваше случайное число 4
    • В противном случае, ваше случайное число 5
  • Если $n_1 = 7$:
    • Спросить у другого человека случайное число ($n_2$)
    • Если $n_2 = 2$ или $ 5$ (20.7%):
      • Ваше случайное число 1
    • Если $n_2 = 8$ или $ 9$ (16.2%):
      • Ваше случайное число 9
    • Если $n_2 = 7$ (28.1%):
      • Ваше случайное число 10
    • В противном случае, ваше случайное число 7
  • Если $n_1 = 8$:
    • Спросить у другого человека случайное число ($n_2$)
    • Если $n_2 = 2$ (8.5%):
      • Ваше случайное число 1
    • В противном случае, ваше случайное число 8
По этому алгоритму вы можете использовать группу людей для получения чего-то близкого к генератору равномерно распределённых случайных чисел от 1 до 10!
Поддержать автора
Поделиться публикацией

Комментарии 72

    +1
    К счастью, если вы готовы примириться с несколькими небольшими неточностями, то из людей можно сделать довольно хороший ГСЧ, не спрашивая более двух раз.

    А как вы построите распределение, которое вы выравниваете? Если вы примиряетесь с неточностями, то можете просто использовать простой ГПСЧ, который можно считать в столбик на бумажке/в уме.
      0
      Может быть взять число пи и брать постепенно цифру за цифрой? А если распределение будет неравномерным — начать выравнивать его при помощи ЛП.
        0
        Инициализировать чем будете? У человека случайное число от 0 до MAX_LONG спросите? Так при таком вопросе распределение очень плохим окажется. И его нормализовать заметно сложнее будет.
        +5
        Все зависит от задачи. Для чего это применяется?
        Для криптографии, например, не подойдет. Для каких то других применений будет достаточно закольцованного списка из 10 чисел. Где то линейный конгруентный метод. И Т. Д.

        Самое простое — попросить кого-нибудь: «Эй, выбери случайное число от одного до десяти!». Человек отвечает: «Семь!». Отлично! Теперь у вас есть число. Однако вы начинаете задаваться вопросом, является ли оно равномерно распределённым?

        ИМХО, если Вам нужно всего одно число, то не нужно задаваться вопросом «является ли оно равномерно распределенным». У Вас нет репрезентативности, чтобы опровергнуть/доказать что либо.
        Поэтому такое число вам подходит. Потому что просто соответствует заданному критерию.
          +2
          Эй, смотрите, я даже кусок вашего кода нашел.
          image
            +1

            А с чего вы взяли, что один и тот же человек каждый раз будет на вопрос "выбери случайное число от 1 до 10" отвечать 7? Пока у вас есть один ответ — вы не можете этого знать.

            +2

            Ну нет. У нас же есть не просто число, у нас есть алгоритм его получения! Так что вопрос про равномерную распределённость корректен.

              0
              семь, Пушкин, нос — имеют репрезентативность в русскоязычной среде.
              0

              Взять массив из 10 чисел и прогнать его перестановками n раз, где n случайное целое число в нужном нам диапазоне?

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

                Интересен другой момент. Допустим, что у нас нет комнаты с людьми, а только мы сами. Нет ни игральной кости, ни чего-либо ещё, только наш организм. Есть ли какой-нибудь способ сгенерировать случайную последовательность, пусть даже очень медленно? Человеческий организм достаточно сложный, в нём много случайных процессов различной природы, соответственно и различных источников энтропии, но можно ли их как-нибудь считать нашими органами чувств и воспроизвести в виде последовательности? Чисто теоретически подобный навык был бы полезен с точки зрения информационной безопасности.
                  0

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

                    0
                    Можно, хотя это нарушает предложенные условия. Часы — внешний источник. Допустим, что у человека нет внешних ориентиров.

                    Приведу пример. Многие, наверное, знакомы со звоном в ушах в очень тихой обстановке. Иногда я у себя замечаю, что в одном ухе тон этого звона дискретно изменяется, т.е. я ощущаю два отчетливых переключающихся тона. Если использовать стук сердца как тактовый генератор, то можно в моменты удара сердца регистрировать тон в ухе. Я так и не проделал этот эксперимент, хотя очень хотелось бы оценить случайность полученной последовательности. Это довольно сложно и не практично, но тем не менее. Возможно есть другие способы?
                      +1
                      Убрать часы можно считая удары сердца за, как человеку кажется, пять минут.
                      0
                      У всех этих способов есть один нюанс, мы должны заранее знать распределение которое получается и надеяться что это распределение не изменяется со временем.
                      Есть способ не рассчитывать на человеческое поведение и рассмотреть другой способ генерации не равномерного распределения.
                      Например спросить имя-фамилию и случайное число, контатенировать и посчить хэш.
                      Так как хэш мы выбираем сами — мы можем узнать его распределение и уже по этим значениям применить продолжение статьи. По моему мнению такой подход будет более логичен.

                      По распределениям хэш-функций много статей не нашел, может плохо искал. Просто для ознакомления и объяснения почему обычно используемые хэш-функции не дают равномерного распределения: research.neustar.biz/2012/02/02/choosing-a-good-hash-function-part-3
                      +1
                      Вариантов куча, главное их придумать и доработать:
                      1. Последовательно плевать в одном направлении, сортировать расстояние до плевков.
                      2. Ронять любой предмет (если есть) на палец и отмечать «успел отдёрнуть или нет».
                      3. Считать количество ударов сердца за время, на которое можете задержать дыхание «и брать простую функцию от этого числа» (с).
                      4. Сидеть и ждать, какая нога раньше зачешется — левая или правая (рандом 0 или 1).
                      Достаточно или ещё нагенерировать?
                        0
                        Вы немного не уловили суть. Прежде всего имелись ввиду способы генерации последовательности из головы без каких-либо внешних вспомогательных средств. Из выше предложенного более-менее подходит последний пункт. А сможете не задумываясь длительное время произносить числа, кажущиеся вам случайными? Если последовательность будет достаточно длинной, то предполагаю, что можно будет статистически с высокой вероятностью предугадать следующее сказанное вами число. И это проблема.
                          0
                          Можно с высокой долей вероятности предположить, что любая последовательность «из головы» или слишком предсказуема или встречающиеся в ней элементы не будут равномерно распределены.
                          Поэтому, в Вашем примере, нужен сторонний источник «вдохновения» (например сделать N оборотов с закрытыми глазами и посмотреть, куда направлен взгляд).
                            0
                            Когда мне было нужно так делать, быстро придумывал и запоминал достаточно большое число (двадцать три миллиона шестьсот восемьдесят шесть тысяч триста восемь — 23686308) и считал числовой корень (9). Вполне себе от 0 до 9 получается. Чем больше число, тем честней будет распределение.
                              0
                              Вполне себе от 0 до 9 получается

                              Всё-таки от 1 до 9, вероятно?

                                0
                                Да, вы абсолютно правы.

                                А ещё можно делать одну итерацию сложения цифр и находить остаток от деления на подходящий делитель.
                        –1

                        можно 6 раз подбросить монетку, полученное двоичное число разделить на 7, прибавить 1 и округлить к ближайшему целому

                          +1
                          без доступа к монетам
                          +5
                          Записываем все ответы на бумажку, затем обрабатываем скользящим окном с шириной и шагом 2:

                          n = n+1: значение отбрасывается
                          n > n+1: возвращается 1
                          n < n+1: возвращается 0


                          Код
                          import matplotlib.pyplot as plt
                          from random import choices
                          from itertools import islice
                          from collections import Counter
                          
                          def human_random(count):
                              numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
                              weights = [3.4, 8.5, 10.0, 9.7, 12.2, 9.8, 28.1, 10.9, 5.4, 1.9]
                              return choices(numbers, weights, k=count)  
                          
                          def chunks(seq, size):
                              it = iter(seq)
                              while True:
                                 chunk = list(islice(it, size))
                                 if not chunk or len(chunk) < size:
                                     return
                                 yield chunk
                          
                          def extract_random(seq):
                              bit = lambda x, y: None if x == y else int(x > y)
                              for n1, n2 in chunks(seq, 2):
                                  x = bit(n1, n2)
                                  if x is None:
                                      continue
                                  yield x
                          
                          def pack_bits(bits):
                              return sum([b << i for i, b in enumerate(reversed(bits))])
                          
                          seq1 = human_random(8500)
                          bits = extract_random(seq1)
                          
                          seq2 = (pack_bits(x) for x in chunks(bits, 4))
                          seq2 = filter(lambda x: 1 <= x <= 10, seq2)
                          
                          human = Counter(seq1)
                          extracted = Counter(seq2)
                          
                          plt.bar(human.keys(), human.values())
                          plt.bar(extracted.keys(), extracted.values())
                          plt.show()


                          Получим битовую последовательность с равномерным распределением 1 и 0, которую уже можно как-нибудь упаковать в 1..10 (правда, чисел на выходе будет сильно меньше). У нас получился самый примитивный "экстрактор случайности фон Неймана".
                          image
                            –2
                            А переставить порядок в ряде чисел от 1 до N никак?
                            Вы продолжаете их спрашивать и считать их ответы, округляя дробные числа и игнорируя тех, кто думает, что диапазон от 1 до 10 включает 0.
                            А также игнорируете тех кто сказал уже названные числа.
                              0
                              что тогда ответит 11й человек, если вариантов всего 10 и все они уже названы?
                                0
                                Видимо игнорировать повторы до момента пока все числа не перечислены, после этого начинается новый цикл генерации. Так же как и новая перестановка порядка чисел.
                              +1

                              Можно попросить двух людей поиграть в какую-нибудь игру, где шансы близки к 50%. Например, в камень-ножницы-бумагу. Получим источник случайных битов, по одному каждый на розыгрыш. Чтобы была заинтересованность играть хорошо, пусть играют на щелбаны.

                                0

                                Если один из них играет лучше, то будет скос

                                  +5
                                  Для игры камень ножницы бумага, 2-ум играющим завязать глаза и заткнуть уши, проигравшего исследователь пинает под ж.пу, сильно и больно.
                                  итого хватит 3-х чел. без всяких 8 500 и математических преобразований которые без компьютера и не выполнишь, хотя по условию его изначально не должно быть.
                                    0
                                    проигравшего исследователь пинает под ж.пу, сильно и больно.

                                    У меня так один товарищ игру в мафию проводил, всем раздал бумажки, что они честные жители, а сам имитировал действия мафии и наслаждался.
                                    0
                                    4 человека играют 2 раза(2 независимые пары, каждая играет 1 раз). Берем XOR от того выиграл ли более высокий игрок или нет(из каждой пары). Таким образом генерируем 6 бит(повторяем 6 раз). Инвертируем каждый 2й бит. Сдвигаем окно из 4х бит на 1 бит вправо если 6й бит==1. Если получаем число вне допустимого range, то переигрываем. Profit.
                                    Ps знаю, это число все ещё не случайно, но bias по максимуму устранен.
                                      0
                                      А по нормальному можно сделать генератор псевдослучайных чисел на основе буфера бинарных чисел. Изначально в нем одни 0и. Берем xnor 9го и 11го числа(выберите сами любые 2 числа). Записываем результат в самый левый бит. Дальше сдвигаем вправо и повторяем n раз пока не выйдет в рабочий режим. Работает на листочке.
                                  +1

                                  Недостаток вашего метода в том, что нужно знать веса случайного распределения. А как насчет примитивной реализации, которая не требует такого знания?


                                  from random import random
                                  
                                  def sample1():
                                      s = random() ** 2
                                      return int(s * 10)
                                  
                                  def sampleN(n=10):
                                      return sum(sample1() for _ in range(n)) % 10

                                  Результат, мне кажется, более чем удовлетворительный:


                                  >>> from collections import Counter
                                  >>> Counter(sample1() for _ in range(10000))
                                  Counter({0: 3250,
                                           1: 1258,
                                           2: 989,
                                           3: 832,
                                           4: 753,
                                           5: 676,
                                           6: 656,
                                           7: 564,
                                           8: 520,
                                           9: 502})
                                  
                                  >>> Counter(sampleN() for _ in range(10000))
                                  Counter({0: 984,
                                           1: 1067,
                                           2: 1037,
                                           3: 997,
                                           4: 957,
                                           5: 979,
                                           6: 1030,
                                           7: 979,
                                           8: 993,
                                           9: 977})
                                    0
                                    .
                                      –1
                                      int getRandomNumber()
                                      {
                                         return 4; // chosen by fair dice roll.
                                                   // guaranteed to be random.
                                      }
                                      кто-то должен это добавить для подобной статьи
                                        0
                                        Господа комментаторы, как вообще можно говорить о применении подобного распределения на практике?
                                        Автор просто взял и свел одно из неслучайных распределений и свел его к равномерному. Вот у 5800 профессоров распределение будет чуть-чуть иным, а если взять распределение цифр от 0 до 9 на куче страниц интернета по любой тематике, то лидировать будет четко единица.
                                        дело ведь в том, что человек нам показал какой-то универсальный алгоритм приведения неслучайных распределений к равномерному с помощью всего двух цифр, не больше и не меньше того.
                                          0
                                          Не универсальный. Им нельзя привести к равномерному распределение:
                                          1-9: вероятность 0.0001
                                          10: вероятность 0.9991
                                          ну и даже в примере это не равномерное, а близкое к равномерному.
                                          +9

                                          Попросить их пронумероваться. Завязать глаза. Заставить ходить и при столкновении кричать свой номер.

                                            +2
                                            Ваша команда:
                                            team
                                              0

                                              Не ну они должны быть более менее одного диаметра и комплекции )

                                            +4
                                            Статье не хватает опроса «назовите случайное число от 1 до 10» с добавочным вариантом 0.
                                              +2

                                              В статье не хватает двух опросов, на случайные числа.
                                              Насколько равномерно в первом опросе будут распределены выборы?
                                              Насколько распределение ответов во втором опросе будет отличаться от первого?

                                                –1
                                                Почему то, сразу вспомнилось про фон Неймана… Монте-Карло Казино :)… рулетка…
                                                  0

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


                                                  А если серьезно, то такая случайность зависит от аудитории. Люди могут сговориться и выдавать все время одно и то же число.

                                                    0
                                                    А ещё можно было делать цикличный сдвиг для каждого опрошенного, как остаток от деления на 10, т.е. спросили у 16 по счету человека — сдвинули на 6, спросили у 5673 — сдвинули на 3
                                                      0
                                                      Спросили у 5 — сдвинули на 5. Спросили у 10-ого — не сдвигаем?

                                                      Ааа, я понял, сорян, сдвигаем результат, а не указатель.
                                                        0
                                                        Это даст равномерное количество разных ответов в совокупности. Но каждое число не будет равномерно распределено. Например если все будут отвечать 7, то вы получите результат где каждое число будет встречаться одинаково часто, но при это это все время будет одна и та же циклическая последовательность.
                                                          0
                                                          и все равно это выглядит лучше, чем иметь 100% чисел 7, и по нулям — остальных
                                                        +2
                                                        Узнаём в какой день месяца родился каждый из опрашиваемых.
                                                        Для чисел от 1 до 10 и от 11 до 20 записываем, соответственно, 1-10. Числа с 1 по 20 — это два готовых к использования искомых диапазона (1-10). Остальных отбрасываем (банально сокращая выборку), чтобы не ломать голову с 29-31 и равномерным распределением ответов 21-28 между нужными нам 1-10.
                                                        Distribution of birthdays by day
                                                          0
                                                          Не в тему, просто интересный факт — как-то работал в компании >100 человек, в которой в ноябре ни у кого не было дней рождений.
                                                            0
                                                            Можно просто называть количество дней до следующей после дня рождения круглой даты (числа месяца).
                                                            0
                                                            Кажется, про что-то подобное статья на хабре уже была (см. раздел «Alias-метод»)
                                                              0

                                                              Там была прямо противоположная задача: получение перекошенного распределения исходя из равномерного.

                                                                0
                                                                Перечитал. Действительно, ошибся
                                                              +1
                                                              Допустим, у нас действительно есть то самое распределение предпочтений чисел:
                                                               1   3.4%
                                                               2   8.5%
                                                               3  10.0%
                                                               4   9.7%
                                                               5  12.2%
                                                               6   9.8%
                                                               7  28.1%
                                                               8  10.9%
                                                               9   5.4%
                                                              10   1.9%
                                                              И мистер X выбрал x, а мисс Y выбрала y. Я утверждаю, что этот несложный алгоритм
                                                              z = [4, 4, 9, 10, 7, 6, 7, 7, 10, 7, 2, 4, 7, 8, 8, 10, 10, 9, 9, 7, 8,
                                                                   1, 4, 9, 8, 10, 3, 10, 3, 4, 5, 6, 1, 5, 8, 8, 9, 7, 7, 9, 3, 2, 3,
                                                                   4, 2, 7, 8, 7, 10, 8, 3, 2, 6, 4, 1, 3, 10, 9, 5, 2, 2, 6, 1, 9, 4,
                                                                   6, 5, 7, 3, 10, 1, 3, 6, 3, 4, 1, 2, 2, 9, 10, 8, 1, 1, 6, 6, 4, 1,
                                                                   8, 2, 5, 6, 6, 3, 5, 4, 1, 2, 6, 2, 10][x * 10 + y - 11]
                                                              даст следующее распределение для z:
                                                               1  9.9870%
                                                               2  9.9881%
                                                               3  9.9896%
                                                               4  9.9901%
                                                               5 10.0029%
                                                               6 10.0058%
                                                               7 10.0063%
                                                               8 10.0077%
                                                               9 10.0080%
                                                              10 10.0146%
                                                              
                                                              Желающие могут убедиться в этом самостоятельно.

                                                              ps Жаль, что с нами нет Бена Торвани (слава богу он не видит эту транскрипцию), уж лучше бы вместо субъективного довольно хороший ГСЧ он выкатил циферки.
                                                                0
                                                                Остаток от деления на 10 суммы всех чисел, названных людьми в комнате, уже будет нормализованно распределён. Кто-нибудь, возьмите перекошенное распределение и обработав его таким образом, опровергните это утверждение.
                                                                  0
                                                                  Предположим, что в этой комнате чуть более 8500 студентов.
                                                                  Зачем же мы будем вас опровергать? Это вы опросите чуть более 8500 студентов и просуммируйте по модулю 10.
                                                                  А в статье предложили обойтись двумя респондентами.
                                                                    0
                                                                    А откуда автор взял своё распределение? Это он сначала опросил всех студентов в комнате. По результату опроса и сформулировал свою кусочную функцию. В другой комнате, к примеру, китайских студентов, которые не любят число 4, будет другое распределение, и алгоритм должен измениться. Ну, а так-то да, я был невнимателен.
                                                                      –1
                                                                      Смотрите, статья вот про что (вы извините меня пожалуйста).
                                                                      Есть какой-то специфический источник случайных чисел. Ну, например, стоите вы на внешнем периметре Садового кольца (простите, взял для примера), и отмечаете: вот черная машина поехала, вот белая, вот красная, вот вишнёвая, вот зелёная, вот салатовая. А глаз-то у вас — алмаз, что вы видите — то в техпаспарте и записано. А еще у вас в распоряжении вся гаишная база; сколько вишнёвых, сколько салатовых.
                                                                      Не, у берегов Мичигана другая статистика. Они там все китайские студенты. Но вы-то на внешнем периметре Садового кольца, все дела.
                                                                      Так понятно, или дать еще интерпретацию?
                                                                    0

                                                                    Выше я привел код и результат

                                                                    0
                                                                    равномерное распределение — это не случайные числа :)
                                                                    это случайный порядок
                                                                      0

                                                                      Просим людей назвать 0 или 1. Ответ каждого чётного инвертируем. Должны получить равномерное распределение 0 и 1. Берем 6 бит. 0 и больше 10 отбрасываем.

                                                                        +1
                                                                        1. К названному числу прибавить номер опрошенного
                                                                        2. Взять остаток деления на 10
                                                                        3. Прибавить 1
                                                                          0
                                                                          Откуда берётся номер опрошенного?
                                                                            0
                                                                            Опрашивающий инкрементирует регистр у себя в голове
                                                                              0
                                                                              Смотрите, вы написали некий алгоритм из трёх пунктов. Я указал на его неполноту, т.е. некорректность. В ответ вы говорите что-то вроде «а здесь у нас будет волшебная заглушка».
                                                                              В самой статье тоже расписан алгоритм — это такая выделенная желтым портянка. Не верх изящества, но вполне корректно.
                                                                              Засада в том, что почти все отметившиеся в коментах портянки не прочли, посыла не поняли, прогнали что-то своё. Если чо — там написано, как, опросив двух человек, получить случайное почти равномерно распределённое число.
                                                                                0

                                                                                "как, опросив двух человек, получить случайное почти равномерно распределённое число"


                                                                                1. Опрашиваем всех
                                                                                2. Опрашиваем двух человек
                                                                                3. Какая-то магия
                                                                                  0
                                                                                  Тут магия вот какого рода:
                                                                                  1. нужно прочитать статью
                                                                                  2. нужно понять прочитанное

                                                                                  Данные об опросе «всех» (некоей «репрезентативной» группы) были взяты откуда-то с Реддита. Потом были сделаны некие допущения, нужные автору, чтобы донести свой замысел. У него, судя по всему, получилось не очень. «Видно, место такое»(с)Жмурки.

                                                                                  Идея автора была в том, что из неравномерного дискретного распределения с маленьким базисом (всего 10 чисел) в полпинка можно породить равномерное. Он показал как это сделать технически и сделал клёвую иконографику.
                                                                                    0
                                                                                    Спасибо, еще раз прочитал и понял.

                                                                                    1. Касательно неполного описания – абсолютно согласен, но и справедливости ради, отмечу, что и в посте не описываются: слышат ли люди друг друга в этой комнате, отсутствуют ли там приверженцы оккультизма, нумерологии и тп. Распределение у разных групп разное.

                                                                                    2. Касательно возможности получить равномерное распределение опрашивая двух человек. Вы же упускаете самое важное – в задаче надо сначала опросить всех в комнате, чтобы получить распределение. А у меня можно этого не делать. И для каждого числа использовать одного опрашиваемого.
                                                                                      0
                                                                                      Да не существует такой практической задачи — сделать ГСЧ из комнанты с людьми. Это неудачный зачин для статьи — вот и всё. А дальше — код на R и прочий матан.
                                                                          0
                                                                          Если подставить непрерывную случайную величину в свою функцию распределения (строго монотонную), то полученная случайная величина будет распределена равномерно на отрезке [0, 1]. Есть подозрения, что здесь тоже что-то хорошее будет. Например, случайная величина будет с равными вероятности принимать значения p_1,..., p_10, где p_i = p(x <= i).
                                                                            –2
                                                                            Представьте, что вам нужно сгенерировать равномерно распределённое случайное число от 1 до 10.

                                                                            Равномерно распределённое случайное число от 1 до 10 - это что такое? Может имеется в виду генератор чисел? Тогда так и надо писать, а не ввергать в недоумение читателей. Хотя, похоже, на любой вопрос находится ответ и не один.

                                                                            Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                                                            Самое читаемое