Мне пришлось сначала переписать твой код, прежде чем я смог его понять:
def OW60(sign=1):
r1 = random.randint (1, 30)
r2 = random.randint (1, 30)
val = sign * (r1 + r2)
islow = (r1<=5) + (r2<=5)
ishigh = (r1>=26) + (r2>=26)
if islow == 2 or ishigh == 2:
return val + OW60(1)
elif islow == 1 and ishigh == 1:
return val + OW60(-1)
else:
return val
Может быть, вы найдете это менее читабельным; Я не знаю. (Проверьте, соответствует ли это тому, что вы имели в виду.) Кроме того, относительно того, как вы используете «результат» в своем коде - знаете ли вы о dict s в Python?
В любом случае, вопросы стиля программирования в стороне: предположим, что F (x) - это CDF из OW60 (1), т.е.
F(x) = the probability that OW60(1) returns a value ≤ x.
Точно так же пусть
G(x) = the probability that OW60(-1) returns a value ≤ x.
Затем вы можете вычислить F (x) из определения, суммируя по всем (30 и 30 раз) возможным значениям результата первого броска. Например, если первый бросок равен (2,3), то вы снова бросите, поэтому этот термин добавляет (1/30) (1/30) (5 + F (x-5)) в выражение для F ( Икс). Таким образом, вы получите какое-то непристойно длинное выражение, например
F(x) = (1/900)(2+F(x-2) + 3+F(x-3) + ... + 59+F(x-59) + 60+F(x-60))
, которая представляет собой сумму более 900 слагаемых, по одному на каждую пару (a, b) в [30] & times; [30]. Пары (a, b) с обоими ≤ 5 или обоими ≥26 имеют член a + b + F (xab), пары с одним ≤5 и одним ≥26 имеют член a + b + G (xab), и у остальных есть такой термин, как (a + b), потому что вы больше не бросаете.
Точно так же у вас есть
G(x) = (1/900)(-2+F(x-2) + (-3)+F(x-3) + ... + (-59)+F(x-59) + (-60)+F(x-60))
Конечно, вы можете собирать коэффициенты; единственные члены F встречаются от F (x-60) до F (x-52) и от F (x-10) до F (x-2) (для a, b≥26 или для обоих ≤5), и единственные члены G, которые встречаются, - от G (x-35) до G (x-27) (для одного из a, b≥26 и другого ≤5), поэтому существует меньше членов, чем 30 членов. В любом случае, определяя вектор V (x) как
V(x) = [F(x-60) G(x-60) ... F(x-2) G(x-2) F(x-1) G(x-1) F(x) G(x)]
(скажем), у вас есть (из этих выражений для F и G) отношение вида
V(x) = A*V(x-1) + B
для соответствующей матрицы A и соответствующего вектора B (который вы можете вычислить), поэтому начиная с начальных значений вида V (x) = [0 0] для x, достаточно малого, вы можете найти F (x) и G (x) для x в диапазоне, который вы хотите произвольно закрыть точность. (И ваша f (x), вероятность броска x, это просто F (x) -F (x-1), так что это тоже получается.)
Возможно, есть лучший способ. Все сказано и сделано, однако, почему ты это делаешь? Какой бы тип распределения вы ни выбрали, существуют хорошие и простые распределения вероятностей с соответствующими параметрами, которые имеют хорошие свойства (например, небольшая дисперсия, односторонние ошибки и т. Д.). Нет причин создавать собственную специальную процедуру для генерации случайных чисел.