Ответ 1
Используйте random.choice(). В этом примере a - ваша нижняя граница, пробег между b и c пропущен, а d - верхняя граница.
import random
numbers = range(a,b) + range(c,d)
r = random.choice(numbers)
Я просмотрел Python Docs (возможно, я неправильно понял), но я не видел, чтобы был способ сделать это (посмотрите ниже) без вызова рекурсивной функции. Я хотел бы создать случайное значение, которое исключает значения в середине.
Иными словами,
Предположим, я хотел, чтобы X
был случайным числом, которое не было в
range(a - b, a + b)
Могу ли я сделать это на первом проходе,
или
1. Должен ли я постоянно генерировать число,
2. Проверьте, есть ли в range()
,
3. Промыть ополаскиватель?
Что касается того, почему я не хочу писать рекурсивную функцию,
1. "чувствует", что мне не нужно
2. набор чисел, которые я делаю для этого, может на самом деле оказаться довольно большим, и
... Я слышал, что переполнение стека плохое, и я могу быть слишком осторожным в этом.
Я уверен, что есть хороший, Pythonic, нерекурсивный способ сделать это.
Используйте random.choice(). В этом примере a - ваша нижняя граница, пробег между b и c пропущен, а d - верхняя граница.
import random
numbers = range(a,b) + range(c,d)
r = random.choice(numbers)
Создайте одно случайное число и нарисуйте его на нужные диапазоны чисел.
Если вы хотите сгенерировать целое число между 1-4
или 7-10
, за исключением 5
и 6
, вы можете:
1-8
2
к результату.Отображение будет:
Random number: 1 2 3 4 5 6 7 8
Result: 1 2 3 4 7 8 9 10
Выполняя это так, вам никогда не нужно "перематывать". Вышеприведенный пример предназначен для целых чисел, но он также может применяться к поплавкам.
Возможным решением было бы просто сдвинуть случайные числа из этого диапазона. Например.
def NormalWORange(a, b, sigma):
r = random.normalvariate(a,sigma)
if r < a:
return r-b
else:
return r+b
Это создало бы нормальное распределение с отверстием в диапазоне (a-b, a + b).
Изменить: если вам нужны целые числа, вам понадобится немного больше работы. Если вам нужны целые числа, находящиеся в диапазоне [c, a-b] или [a + b, d], то следующее должно сделать трюк.
def RangeWORange(a, b, c, d):
r = random.randrange(c,d-2*b) # 2*b because two intervals of length b to exclude
if r >= a-b:
return r+2*b
else:
return r
Возможно, я неправильно понял вашу проблему, но вы можете реализовать это без рекурсии
def rand(exclude):
r = None
while r in exclude or r is None:
r = random.randrange(1,10)
return r
rand([1,3,9])
хотя вы все еще просматриваете результаты, пока не найдете новые.
Самое быстрое решение будет таким: (a и b определяют зону исключения, а c и d - набор хороших ответов, включая зону исключения):
offset = b - a
maximum = d - offset
result = random.randrange(c, maximum)
if result >= a:
result += offset
Вам по-прежнему нужен некоторый диапазон, т.е. возможное значение min-max, исключая ваши средние значения.
Почему бы вам сначала не случайно выбрать, какую половину диапазона вы хотите, а затем выбрать случайное число в этом диапазоне? Например:.
def rand_not_in_range(a,b):
rangechoices = ((0,a-b-1),(a+b+1, 10000000))
# Pick a half
fromrange = random.choice(rangechoices)
# return int from that range
return random.randint(*fromrange)
Li-Аун Yip ответ делает выпуск рекурсии спорным, но я должен отметить, что это возможно сделать любую степень рекурсии, не заботясь о стеке. Это называется "хвостовая рекурсия". Python не поддерживает хвостовую рекурсию напрямую, потому что GvR думает, что это uncool:
http://neopythonic.blogspot.com/2009/04/tail-recursion-elimination.html
Но вы можете обойти это:
http://paulbutler.org/archives/tail-recursion-in-python/
Мне интересно, что палка считает, что рекурсия "чувствует себя не так". В чрезвычайно функционально-ориентированных языках, таких как Scheme, рекурсия неизбежна. Он позволяет выполнять итерацию без создания переменных состояния, которые парадигма функционального программирования строго избегает.