Генерация случайного числа, исключающего диапазон

#language-agnostic #random

Вопрос:

Как вы генерируете случайное число в диапазоне, исключая определенные диапазоны. Например, диапазон 1-10, но не 2-4 или 7. Решения, которые я использовал до сих пор:

  • Сгенерируйте случайный тест, если он находится в допустимом диапазоне. На основе результата либо выведите номер, либо повторите попытку.
  • Сопоставьте допустимые диапазоны с единым диапазоном. Получите случайное число от 1 до 6, а затем сопоставьте его (т. е. 6 становится 10).
  • Создайте допустимые диапазоны (1-1,5-6,8-10). Случайным образом выберите диапазон (при необходимости используйте веса) и число в выбранном диапазоне.

Каково ваше решение?

Ответ №1:

(b) Используйте один диапазон и сопоставьте его с допустимыми значениями.

(a) Работает медленнее, и время выполнения не является детерминированным, потому что вам нужно подождать, пока вы не получите число в нужном диапазоне. Если бы вы пропустили большой диапазон, вас бы облили из шланга.

(c) Сложнее, чем (b); не добавляйте сложности, если это не требуется.

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

1. (c) также должны использоваться взвешенные диапазоны. В противном случае рассмотрите: 0..10, 20..80, 90..100; существует три диапазона, но если выбрать диапазоны с одинаковой вероятностью, то вы увидите очень искаженные результаты.

2. Да, если распределение важно (отсюда мое утверждение о необязательном использовании весов). Кроме того, я знаю о недостатках каждого метода — я задавался вопросом, есть ли более элегантное решение 🙂

Ответ №2:

Это будет зависеть от того, сколько/больших диапазонов исключений. Тестирование на допустимый диапазон (ваш вариант 1) будет отлично работать для небольших наборов; не нужно усложнять решение простой проблемы. Решение 3 будет лучше работать для более многочисленных наборов исключений. Решение 2-самое сложное, но, вероятно, самое правильное теоретическое решение.

Ответ №3:

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

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

Ответ №4:

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

Например, если вам нужна случайная величина от 0..10 до 100..110

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

Причина этого в том, что вы часто имеете дело с неидеальными генераторами случайных чисел. Они начинают вести себя странно, если вы распределяете последовательные переменные случайных чисел по нескольким измерениям (например, сначала выбираете случайный интервал, затем выбираете случайный внутри выбранного интервала). Это может привести к очень очевидному неслучайному поведению.

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

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

1. Боюсь, что по одному в каждом из двух диапазонов (11 значений в диапазоне 0..10; аналогично 100..110).

Ответ №5:

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

Например, если вы хотите получить случайную серию чисел от 1 до 10, лучше начать с упорядоченной серии, смешать ее каким-то образом, например, путем замены (я думаю, был вопрос об этом) и взять числа одно за другим.