TGViewer
Чайник из Юты Чайник из Юты @irrationalthings · 121 subscribers
Post #542 317
Rejection Sampling and Uniform Distribution

Одна из характеристик хорошей rand-функции — равномерное распределение. Это означает, что каждое возможное значение имеет одинаковую вероятность быть выбрано

Представим, что у вас есть функция rand7(), которая равномерно возвращает случайное число в диапазоне [1, 7]. Наша задача — написать функцию rand10() с диапазоном [1, 10], сохранив равномерное распределение. Дальше вместо rand7() будут использоваться переменные a и b. Скорее всего, вы сходу предложите одну из примитивных реализаций. Вот примеры:

func rand10() int {  
a, b := rand7(), rand7()
return a + b % 3
}


func rand10() int {  
a, b := rand7(), rand7()
return (a * b) % 10 + 1
}


Обе реализации неправильны

В первом варианте b % 3 даёт остатки от деления на 3, т.е. 0, 1 или 2 не с одинаковой вероятностью. Остаток 1 встречается чаще остальных, из-за чего получается неравномерное распределение итоговых значений.

Во втором варианте количество способов получить каждое произведение a * b тоже неравномерное.
Например:
- 1 = 1 * 1 → 1 комбинация
- 6 = 1*6, 2*3, 3*2, 6*1 → 4 комбинации
- 12 = 2*6, 3*4, 4*3, 6*2 → 4 комбинации
- 36 = 6*6 → 1 комбинация
и так далее

(...) % 10 + 1 ещё больше усугубляет ситуацию, потому что например при product = 2, 12, 22, 32, 42 мы будем везде получать значение 3

На графиках можно наглядно увидеть перекос, перебрав все 49 возможных комбинаций a и b.

Правильное решение

Рассмотрим формулу:
((a - 1) * 7 + b ) % 10 + 1

Она почти равномерна: значения от 1 до 10 встречаются почти с одинаковой частотой, за исключением 10, которое появляется всего 4 раза, тогда как остальные — по 5 раз.

Причина проста - всего комбинаций 7 × 7 = 49, нам не хватает числа 50.

Можно ли без него? Можно - проблема решается с помощью rejection sampling - мы отбрасываем значения больше 40. На языке кода мы делем пересчёт if num > 40. Тогда остаются только 40 комбинаций, которые можно равномерно разбить на 10 групп по 4 значения, что и видно на последней диаграмме

Финальный код:
func rand10() int {  
for {
a, b := rand7(), rand7()
num := (a-1)*7 + b

if num <= 40 {
return 1 + (num-1)%10
}
}
}


Задача на Leetcode: https://leetcode.com/problems/implement-rand10-using-rand7/
  • 👍 5
More from @irrationalthings
  1. Sep 21, 2026я хрюкнул
  2. Sep 21, 2026гемини
  3. Sep 15, 2026Тот факт, что между нейронками и компрессорами больше общего, чем может показаться - забав…
  4. Sep 15, 2026"Low-Resource" Text Classification: A Parameter-Free Classification Method with Compressor…
  5. Sep 15, 2026Конечно, они сравнивали со средненькими классифицирующими моделями. Там есть пространство…
  6. Sep 15, 2026GZIP наносит ответный удар Вот мы хотим классифицировать текст. Классическая задача для ML…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →